16f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/*
26f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Copyright (C) 2015 The Android Open Source Project
36f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski *
46f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
56f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * you may not use this file except in compliance with the License.
66f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * You may obtain a copy of the License at
76f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski *
86f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
96f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski *
106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Unless required by applicable law or agreed to in writing, software
116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * See the License for the specific language governing permissions and
146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * limitations under the License.
156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */
166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#ifndef AAPT_MAYBE_H
186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#define AAPT_MAYBE_H
196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
20803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski#include "util/TypeTraits.h"
21803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski
226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <cassert>
236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <type_traits>
246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <utility>
256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskinamespace aapt {
276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/**
296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Either holds a valid value of type T, or holds Nothing.
306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * The value is stored inline in this structure, so no
316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * heap memory is used when creating a Maybe<T> object.
326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */
336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiclass Maybe {
356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskipublic:
366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    /**
376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * Construct Nothing.
386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     */
3924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe();
406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
4124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    ~Maybe();
4224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
4324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe(const Maybe& rhs);
446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
456f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    template <typename U>
4624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe(const Maybe<U>& rhs);
4724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
4824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe(Maybe&& rhs);
496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    template <typename U>
5124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe(Maybe<U>&& rhs);
5224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
5324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe& operator=(const Maybe& rhs);
546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    template <typename U>
5624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe& operator=(const Maybe<U>& rhs);
5724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
5824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe& operator=(Maybe&& rhs);
596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    template <typename U>
6124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe& operator=(Maybe<U>&& rhs);
626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    /**
646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * Construct a Maybe holding a value.
656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     */
6624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe(const T& value);
676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    /**
696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * Construct a Maybe holding a value.
706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     */
7124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe(T&& value);
726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    /**
746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * True if this holds a value, false if
756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * it holds Nothing.
766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     */
771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    explicit operator bool() const;
786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    /**
806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * Gets the value if one exists, or else
816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * panics.
826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     */
8324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    T& value();
846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    /**
866f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * Gets the value if one exists, or else
876f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * panics.
886f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     */
8924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    const T& value() const;
906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiprivate:
926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    template <typename U>
936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    friend class Maybe;
946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
9524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    template <typename U>
9624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe& copy(const Maybe<U>& rhs);
9724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
9824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    template <typename U>
9924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe& move(Maybe<U>&& rhs);
10024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
1016f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    void destroy();
1026f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    bool mNothing;
1046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    typename std::aligned_storage<sizeof(T), alignof(T)>::type mStorage;
1066f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski};
1076f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1086f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
1096f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiMaybe<T>::Maybe()
1106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski: mNothing(true) {
1116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
1146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiMaybe<T>::~Maybe() {
1156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    if (!mNothing) {
1166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        destroy();
1176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    }
1186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
12124aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiMaybe<T>::Maybe(const Maybe& rhs)
12224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski: mNothing(rhs.mNothing) {
12324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    if (!rhs.mNothing) {
12424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski        new (&mStorage) T(reinterpret_cast<const T&>(rhs.mStorage));
12524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    }
12624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski}
12724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
12824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskitemplate <typename T>
1296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename U>
1306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiMaybe<T>::Maybe(const Maybe<U>& rhs)
1316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski: mNothing(rhs.mNothing) {
1326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    if (!rhs.mNothing) {
1336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        new (&mStorage) T(reinterpret_cast<const U&>(rhs.mStorage));
1346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    }
1356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
13824aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiMaybe<T>::Maybe(Maybe&& rhs)
13924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski: mNothing(rhs.mNothing) {
14024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    if (!rhs.mNothing) {
14124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski        rhs.mNothing = true;
14224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
14324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski        // Move the value from rhs.
14424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski        new (&mStorage) T(std::move(reinterpret_cast<T&>(rhs.mStorage)));
14524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski        rhs.destroy();
14624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    }
14724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski}
14824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
14924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskitemplate <typename T>
1506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename U>
1516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiMaybe<T>::Maybe(Maybe<U>&& rhs)
1526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski: mNothing(rhs.mNothing) {
1536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    if (!rhs.mNothing) {
1546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        rhs.mNothing = true;
1556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        // Move the value from rhs.
1576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        new (&mStorage) T(std::move(reinterpret_cast<U&>(rhs.mStorage)));
1586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        rhs.destroy();
1596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    }
1606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
16324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskiinline Maybe<T>& Maybe<T>::operator=(const Maybe& rhs) {
16424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    // Delegate to the actual assignment.
16524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    return copy(rhs);
16624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski}
16724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
16824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskitemplate <typename T>
16924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskitemplate <typename U>
17024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskiinline Maybe<T>& Maybe<T>::operator=(const Maybe<U>& rhs) {
17124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    return copy(rhs);
17224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski}
17324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
17424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskitemplate <typename T>
1756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename U>
17624aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiMaybe<T>& Maybe<T>::copy(const Maybe<U>& rhs) {
1776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    if (mNothing && rhs.mNothing) {
1786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        // Both are nothing, nothing to do.
1796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        return *this;
1806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    } else if  (!mNothing && !rhs.mNothing) {
1816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        // We both are something, so assign rhs to us.
1826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        reinterpret_cast<T&>(mStorage) = reinterpret_cast<const U&>(rhs.mStorage);
1836f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    } else if (mNothing) {
1846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        // We are nothing but rhs is something.
1856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        mNothing = rhs.mNothing;
1866f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1876f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        // Copy the value from rhs.
1886f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        new (&mStorage) T(reinterpret_cast<const U&>(rhs.mStorage));
1896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    } else {
1906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        // We are something but rhs is nothing, so destroy our value.
1916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        mNothing = rhs.mNothing;
1926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        destroy();
1936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    }
1946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return *this;
1956f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1966f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1976f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
19824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskiinline Maybe<T>& Maybe<T>::operator=(Maybe&& rhs) {
19924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    // Delegate to the actual assignment.
20024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    return move(std::forward<Maybe<T>>(rhs));
20124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski}
20224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
20324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskitemplate <typename T>
20424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskitemplate <typename U>
20524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskiinline Maybe<T>& Maybe<T>::operator=(Maybe<U>&& rhs) {
20624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    return move(std::forward<Maybe<U>>(rhs));
20724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski}
20824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
20924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskitemplate <typename T>
2106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename U>
21124aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiMaybe<T>& Maybe<T>::move(Maybe<U>&& rhs) {
2126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    if (mNothing && rhs.mNothing) {
2136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        // Both are nothing, nothing to do.
2146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        return *this;
2156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    } else if  (!mNothing && !rhs.mNothing) {
2166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        // We both are something, so move assign rhs to us.
2176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        rhs.mNothing = true;
2186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        reinterpret_cast<T&>(mStorage) = std::move(reinterpret_cast<U&>(rhs.mStorage));
2196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        rhs.destroy();
2206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    } else if (mNothing) {
2216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        // We are nothing but rhs is something.
22224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski        mNothing = false;
22324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski        rhs.mNothing = true;
2246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        // Move the value from rhs.
2266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        new (&mStorage) T(std::move(reinterpret_cast<U&>(rhs.mStorage)));
2276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        rhs.destroy();
2286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    } else {
2296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        // We are something but rhs is nothing, so destroy our value.
23024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski        mNothing = true;
2316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        destroy();
2326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    }
2336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return *this;
2346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
2376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiMaybe<T>::Maybe(const T& value)
2386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski: mNothing(false) {
2396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    new (&mStorage) T(value);
2406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
2436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiMaybe<T>::Maybe(T&& value)
2446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski: mNothing(false) {
2456f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    new (&mStorage) T(std::forward<T>(value));
2466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
2496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiMaybe<T>::operator bool() const {
2506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return !mNothing;
2516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
2546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiT& Maybe<T>::value() {
2556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    assert(!mNothing && "Maybe<T>::value() called on Nothing");
2566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return reinterpret_cast<T&>(mStorage);
2576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
2606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiconst T& Maybe<T>::value() const {
2616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    assert(!mNothing && "Maybe<T>::value() called on Nothing");
2626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return reinterpret_cast<const T&>(mStorage);
2636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
2666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskivoid Maybe<T>::destroy() {
2676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    reinterpret_cast<T&>(mStorage).~T();
2686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
2716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline Maybe<typename std::remove_reference<T>::type> make_value(T&& value) {
2726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return Maybe<typename std::remove_reference<T>::type>(std::forward<T>(value));
2736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
2766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline Maybe<T> make_nothing() {
2776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return Maybe<T>();
2786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
280a587065721053ad54e34f484868142407d59512dAdam Lesinski/**
281803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski * Define the == operator between Maybe<T> and Maybe<U> only if the operator T == U is defined.
282803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski * That way the compiler will show an error at the callsite when comparing two Maybe<> objects
283803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski * whose inner types can't be compared.
284a587065721053ad54e34f484868142407d59512dAdam Lesinski */
285a587065721053ad54e34f484868142407d59512dAdam Lesinskitemplate <typename T, typename U>
286803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinskitypename std::enable_if<
287803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski        has_eq_op<T, U>::value,
288803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski        bool
289803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski>::type operator==(const Maybe<T>& a, const Maybe<U>& b) {
290a587065721053ad54e34f484868142407d59512dAdam Lesinski    if (a && b) {
291a587065721053ad54e34f484868142407d59512dAdam Lesinski        return a.value() == b.value();
292a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski    } else if (!a && !b) {
293a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski        return true;
294a587065721053ad54e34f484868142407d59512dAdam Lesinski    }
295a587065721053ad54e34f484868142407d59512dAdam Lesinski    return false;
296a587065721053ad54e34f484868142407d59512dAdam Lesinski}
297a587065721053ad54e34f484868142407d59512dAdam Lesinski
298a587065721053ad54e34f484868142407d59512dAdam Lesinski/**
299a587065721053ad54e34f484868142407d59512dAdam Lesinski * Same as operator== but negated.
300a587065721053ad54e34f484868142407d59512dAdam Lesinski */
301a587065721053ad54e34f484868142407d59512dAdam Lesinskitemplate <typename T, typename U>
302803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinskitypename std::enable_if<
303803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski        has_eq_op<T, U>::value,
304803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski        bool
305803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski>::type operator!=(const Maybe<T>& a, const Maybe<U>& b) {
306a587065721053ad54e34f484868142407d59512dAdam Lesinski    return !(a == b);
307a587065721053ad54e34f484868142407d59512dAdam Lesinski}
308a587065721053ad54e34f484868142407d59512dAdam Lesinski
3096f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} // namespace aapt
3106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
3116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#endif // AAPT_MAYBE_H
312