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