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
206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <cassert>
216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <type_traits>
226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <utility>
236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskinamespace aapt {
256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/**
276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Either holds a valid value of type T, or holds Nothing.
286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * The value is stored inline in this structure, so no
296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * heap memory is used when creating a Maybe<T> object.
306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */
316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiclass Maybe {
336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskipublic:
346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    /**
356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * Construct Nothing.
366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     */
3724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe();
386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
3924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    ~Maybe();
4024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
4124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe(const Maybe& rhs);
426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    template <typename U>
4424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe(const Maybe<U>& rhs);
4524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
4624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe(Maybe&& rhs);
476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    template <typename U>
4924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe(Maybe<U>&& rhs);
5024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
5124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe& operator=(const Maybe& rhs);
526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    template <typename U>
5424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe& operator=(const Maybe<U>& rhs);
5524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
5624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe& operator=(Maybe&& rhs);
576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    template <typename U>
5924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe& operator=(Maybe<U>&& rhs);
606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    /**
626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * Construct a Maybe holding a value.
636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     */
6424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe(const T& value);
656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    /**
676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * Construct a Maybe holding a value.
686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     */
6924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe(T&& value);
706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    /**
726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * True if this holds a value, false if
736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * it holds Nothing.
746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     */
7524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    operator bool() const;
766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    /**
786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * Gets the value if one exists, or else
796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * panics.
806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     */
8124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    T& value();
826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
836f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    /**
846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * Gets the value if one exists, or else
856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * panics.
866f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     */
8724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    const T& value() const;
886f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiprivate:
906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    template <typename U>
916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    friend class Maybe;
926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
9324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    template <typename U>
9424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe& copy(const Maybe<U>& rhs);
9524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
9624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    template <typename U>
9724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    Maybe& move(Maybe<U>&& rhs);
9824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
996f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    void destroy();
1006f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1016f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    bool mNothing;
1026f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    typename std::aligned_storage<sizeof(T), alignof(T)>::type mStorage;
1046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski};
1056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1066f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
1076f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiMaybe<T>::Maybe()
1086f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski: mNothing(true) {
1096f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
1126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiMaybe<T>::~Maybe() {
1136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    if (!mNothing) {
1146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        destroy();
1156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    }
1166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
11924aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiMaybe<T>::Maybe(const Maybe& rhs)
12024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski: mNothing(rhs.mNothing) {
12124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    if (!rhs.mNothing) {
12224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski        new (&mStorage) T(reinterpret_cast<const T&>(rhs.mStorage));
12324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    }
12424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski}
12524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
12624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskitemplate <typename T>
1276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename U>
1286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiMaybe<T>::Maybe(const Maybe<U>& rhs)
1296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski: mNothing(rhs.mNothing) {
1306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    if (!rhs.mNothing) {
1316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        new (&mStorage) T(reinterpret_cast<const U&>(rhs.mStorage));
1326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    }
1336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
13624aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiMaybe<T>::Maybe(Maybe&& rhs)
13724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski: mNothing(rhs.mNothing) {
13824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    if (!rhs.mNothing) {
13924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski        rhs.mNothing = true;
14024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
14124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski        // Move the value from rhs.
14224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski        new (&mStorage) T(std::move(reinterpret_cast<T&>(rhs.mStorage)));
14324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski        rhs.destroy();
14424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    }
14524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski}
14624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
14724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskitemplate <typename T>
1486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename U>
1496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiMaybe<T>::Maybe(Maybe<U>&& rhs)
1506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski: mNothing(rhs.mNothing) {
1516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    if (!rhs.mNothing) {
1526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        rhs.mNothing = true;
1536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        // Move the value from rhs.
1556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        new (&mStorage) T(std::move(reinterpret_cast<U&>(rhs.mStorage)));
1566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        rhs.destroy();
1576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    }
1586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
16124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskiinline Maybe<T>& Maybe<T>::operator=(const Maybe& rhs) {
16224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    // Delegate to the actual assignment.
16324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    return copy(rhs);
16424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski}
16524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
16624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskitemplate <typename T>
16724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskitemplate <typename U>
16824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskiinline Maybe<T>& Maybe<T>::operator=(const Maybe<U>& rhs) {
16924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    return copy(rhs);
17024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski}
17124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
17224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskitemplate <typename T>
1736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename U>
17424aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiMaybe<T>& Maybe<T>::copy(const Maybe<U>& rhs) {
1756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    if (mNothing && rhs.mNothing) {
1766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        // Both are nothing, nothing to do.
1776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        return *this;
1786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    } else if  (!mNothing && !rhs.mNothing) {
1796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        // We both are something, so assign rhs to us.
1806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        reinterpret_cast<T&>(mStorage) = reinterpret_cast<const U&>(rhs.mStorage);
1816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    } else if (mNothing) {
1826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        // We are nothing but rhs is something.
1836f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        mNothing = rhs.mNothing;
1846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        // Copy the value from rhs.
1866f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        new (&mStorage) T(reinterpret_cast<const U&>(rhs.mStorage));
1876f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    } else {
1886f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        // We are something but rhs is nothing, so destroy our value.
1896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        mNothing = rhs.mNothing;
1906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        destroy();
1916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    }
1926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return *this;
1936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1956f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
19624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskiinline Maybe<T>& Maybe<T>::operator=(Maybe&& rhs) {
19724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    // Delegate to the actual assignment.
19824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    return move(std::forward<Maybe<T>>(rhs));
19924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski}
20024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
20124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskitemplate <typename T>
20224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskitemplate <typename U>
20324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskiinline Maybe<T>& Maybe<T>::operator=(Maybe<U>&& rhs) {
20424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    return move(std::forward<Maybe<U>>(rhs));
20524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski}
20624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
20724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinskitemplate <typename T>
2086f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename U>
20924aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiMaybe<T>& Maybe<T>::move(Maybe<U>&& rhs) {
2106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    if (mNothing && rhs.mNothing) {
2116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        // Both are nothing, nothing to do.
2126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        return *this;
2136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    } else if  (!mNothing && !rhs.mNothing) {
2146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        // We both are something, so move assign rhs to us.
2156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        rhs.mNothing = true;
2166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        reinterpret_cast<T&>(mStorage) = std::move(reinterpret_cast<U&>(rhs.mStorage));
2176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        rhs.destroy();
2186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    } else if (mNothing) {
2196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        // We are nothing but rhs is something.
22024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski        mNothing = false;
22124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski        rhs.mNothing = true;
2226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        // Move the value from rhs.
2246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        new (&mStorage) T(std::move(reinterpret_cast<U&>(rhs.mStorage)));
2256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        rhs.destroy();
2266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    } else {
2276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        // We are something but rhs is nothing, so destroy our value.
22824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski        mNothing = true;
2296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        destroy();
2306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    }
2316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return *this;
2326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
2356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiMaybe<T>::Maybe(const T& value)
2366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski: mNothing(false) {
2376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    new (&mStorage) T(value);
2386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
2416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiMaybe<T>::Maybe(T&& value)
2426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski: mNothing(false) {
2436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    new (&mStorage) T(std::forward<T>(value));
2446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2456f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
2476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiMaybe<T>::operator bool() const {
2486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return !mNothing;
2496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
2526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiT& Maybe<T>::value() {
2536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    assert(!mNothing && "Maybe<T>::value() called on Nothing");
2546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return reinterpret_cast<T&>(mStorage);
2556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
2586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiconst T& Maybe<T>::value() const {
2596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    assert(!mNothing && "Maybe<T>::value() called on Nothing");
2606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return reinterpret_cast<const T&>(mStorage);
2616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
2646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskivoid Maybe<T>::destroy() {
2656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    reinterpret_cast<T&>(mStorage).~T();
2666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
2696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline Maybe<typename std::remove_reference<T>::type> make_value(T&& value) {
2706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return Maybe<typename std::remove_reference<T>::type>(std::forward<T>(value));
2716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskitemplate <typename T>
2746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline Maybe<T> make_nothing() {
2756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return Maybe<T>();
2766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} // namespace aapt
2796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#endif // AAPT_MAYBE_H
281