1*14675a02SAndroid Build Coastguard Worker /* 2*14675a02SAndroid Build Coastguard Worker * Copyright 2019 Google LLC 3*14675a02SAndroid Build Coastguard Worker * 4*14675a02SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*14675a02SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*14675a02SAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*14675a02SAndroid Build Coastguard Worker * 8*14675a02SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*14675a02SAndroid Build Coastguard Worker * 10*14675a02SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*14675a02SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*14675a02SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*14675a02SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*14675a02SAndroid Build Coastguard Worker * limitations under the License. 15*14675a02SAndroid Build Coastguard Worker */ 16*14675a02SAndroid Build Coastguard Worker 17*14675a02SAndroid Build Coastguard Worker #ifndef FCP_BASE_UNIQUE_VALUE_H_ 18*14675a02SAndroid Build Coastguard Worker #define FCP_BASE_UNIQUE_VALUE_H_ 19*14675a02SAndroid Build Coastguard Worker 20*14675a02SAndroid Build Coastguard Worker #include <optional> 21*14675a02SAndroid Build Coastguard Worker #include <utility> 22*14675a02SAndroid Build Coastguard Worker 23*14675a02SAndroid Build Coastguard Worker namespace fcp { 24*14675a02SAndroid Build Coastguard Worker 25*14675a02SAndroid Build Coastguard Worker /** 26*14675a02SAndroid Build Coastguard Worker * UniqueValue<T> provides move-only semantics for some value of type T. 27*14675a02SAndroid Build Coastguard Worker * 28*14675a02SAndroid Build Coastguard Worker * Its semantics are much like std::unique_ptr, but without requiring an 29*14675a02SAndroid Build Coastguard Worker * allocation and pointer indirection (recall a moved-from std::unique_ptr is 30*14675a02SAndroid Build Coastguard Worker * reset to nullptr). 31*14675a02SAndroid Build Coastguard Worker * 32*14675a02SAndroid Build Coastguard Worker * Instead, UniqueValue is represented just like std::optional - but 33*14675a02SAndroid Build Coastguard Worker * has_value() == false once moved-from. std::optional does *not* reset when 34*14675a02SAndroid Build Coastguard Worker * moved from (even if the wrapped type is move-only); that's consistent, but 35*14675a02SAndroid Build Coastguard Worker * not especially desirable. 36*14675a02SAndroid Build Coastguard Worker * 37*14675a02SAndroid Build Coastguard Worker * Since UniqueValue is always move-only, including a UniqueValue member is 38*14675a02SAndroid Build Coastguard Worker * sufficient for a containing aggregate to be move-only. 39*14675a02SAndroid Build Coastguard Worker */ 40*14675a02SAndroid Build Coastguard Worker template <typename T> 41*14675a02SAndroid Build Coastguard Worker class UniqueValue { 42*14675a02SAndroid Build Coastguard Worker public: UniqueValue(std::nullopt_t)43*14675a02SAndroid Build Coastguard Worker constexpr explicit UniqueValue(std::nullopt_t) : value_() {} UniqueValue(T val)44*14675a02SAndroid Build Coastguard Worker constexpr explicit UniqueValue(T val) : value_(std::move(val)) {} 45*14675a02SAndroid Build Coastguard Worker 46*14675a02SAndroid Build Coastguard Worker UniqueValue(UniqueValue const&) = delete; UniqueValue(UniqueValue && other)47*14675a02SAndroid Build Coastguard Worker UniqueValue(UniqueValue&& other) : value_(std::move(other.value_)) { 48*14675a02SAndroid Build Coastguard Worker other.value_.reset(); 49*14675a02SAndroid Build Coastguard Worker } 50*14675a02SAndroid Build Coastguard Worker 51*14675a02SAndroid Build Coastguard Worker UniqueValue& operator=(UniqueValue other) { 52*14675a02SAndroid Build Coastguard Worker value_.swap(other.value_); 53*14675a02SAndroid Build Coastguard Worker return *this; 54*14675a02SAndroid Build Coastguard Worker } 55*14675a02SAndroid Build Coastguard Worker 56*14675a02SAndroid Build Coastguard Worker /** 57*14675a02SAndroid Build Coastguard Worker * Indicates if this instance holds a value (i.e. has not been moved away). 58*14675a02SAndroid Build Coastguard Worker * 59*14675a02SAndroid Build Coastguard Worker * It is an error to dereference this UniqueValue if !has_value(). 60*14675a02SAndroid Build Coastguard Worker */ has_value()61*14675a02SAndroid Build Coastguard Worker constexpr bool has_value() const { 62*14675a02SAndroid Build Coastguard Worker return value_.has_value(); 63*14675a02SAndroid Build Coastguard Worker } 64*14675a02SAndroid Build Coastguard Worker Take()65*14675a02SAndroid Build Coastguard Worker constexpr T Take() && { 66*14675a02SAndroid Build Coastguard Worker T v = *std::move(value_); 67*14675a02SAndroid Build Coastguard Worker value_.reset(); 68*14675a02SAndroid Build Coastguard Worker return v; 69*14675a02SAndroid Build Coastguard Worker } 70*14675a02SAndroid Build Coastguard Worker 71*14675a02SAndroid Build Coastguard Worker constexpr T const& operator*() const & { 72*14675a02SAndroid Build Coastguard Worker return *value_; 73*14675a02SAndroid Build Coastguard Worker } 74*14675a02SAndroid Build Coastguard Worker 75*14675a02SAndroid Build Coastguard Worker T& operator*() & { 76*14675a02SAndroid Build Coastguard Worker return *value_; 77*14675a02SAndroid Build Coastguard Worker } 78*14675a02SAndroid Build Coastguard Worker 79*14675a02SAndroid Build Coastguard Worker T const* operator->() const { 80*14675a02SAndroid Build Coastguard Worker return &*value_; 81*14675a02SAndroid Build Coastguard Worker } 82*14675a02SAndroid Build Coastguard Worker 83*14675a02SAndroid Build Coastguard Worker T* operator->() { 84*14675a02SAndroid Build Coastguard Worker return &*value_; 85*14675a02SAndroid Build Coastguard Worker } 86*14675a02SAndroid Build Coastguard Worker 87*14675a02SAndroid Build Coastguard Worker /** 88*14675a02SAndroid Build Coastguard Worker * Replaces current value with a newly constructed one given constructor 89*14675a02SAndroid Build Coastguard Worker * arguments for T (like std::optional::emplace). 90*14675a02SAndroid Build Coastguard Worker */ 91*14675a02SAndroid Build Coastguard Worker template <class... _Args> Emplace(_Args &&...__args)92*14675a02SAndroid Build Coastguard Worker T& Emplace(_Args&&... __args) { 93*14675a02SAndroid Build Coastguard Worker value_.emplace(std::forward<_Args>(__args)...); 94*14675a02SAndroid Build Coastguard Worker return *value_; 95*14675a02SAndroid Build Coastguard Worker } 96*14675a02SAndroid Build Coastguard Worker 97*14675a02SAndroid Build Coastguard Worker /** 98*14675a02SAndroid Build Coastguard Worker * Removes (destructs) a value. No-op if absent; 99*14675a02SAndroid Build Coastguard Worker */ Reset()100*14675a02SAndroid Build Coastguard Worker void Reset() { value_.reset(); } 101*14675a02SAndroid Build Coastguard Worker 102*14675a02SAndroid Build Coastguard Worker private: 103*14675a02SAndroid Build Coastguard Worker std::optional<T> value_; 104*14675a02SAndroid Build Coastguard Worker }; 105*14675a02SAndroid Build Coastguard Worker 106*14675a02SAndroid Build Coastguard Worker // Deduction guide allowing one to write UniqueValue(x) without an explicit 107*14675a02SAndroid Build Coastguard Worker // template argument. This one would be implicitly generated; it's here to 108*14675a02SAndroid Build Coastguard Worker // suppress -Wctad-maybe-unsupported. 109*14675a02SAndroid Build Coastguard Worker template <typename T> 110*14675a02SAndroid Build Coastguard Worker UniqueValue(T val) -> UniqueValue<T>; 111*14675a02SAndroid Build Coastguard Worker 112*14675a02SAndroid Build Coastguard Worker /** 113*14675a02SAndroid Build Coastguard Worker * Makes a UniqueValue<T> given constructor arguments for T 114*14675a02SAndroid Build Coastguard Worker * (like std::make_unique). 115*14675a02SAndroid Build Coastguard Worker */ 116*14675a02SAndroid Build Coastguard Worker template <typename T, typename... Args> MakeUniqueValue(Args &&...args)117*14675a02SAndroid Build Coastguard Workerconstexpr UniqueValue<T> MakeUniqueValue(Args&&... args) { 118*14675a02SAndroid Build Coastguard Worker return UniqueValue<T>(T(std::forward<Args>(args)...)); 119*14675a02SAndroid Build Coastguard Worker } 120*14675a02SAndroid Build Coastguard Worker 121*14675a02SAndroid Build Coastguard Worker } // namespace fcp 122*14675a02SAndroid Build Coastguard Worker 123*14675a02SAndroid Build Coastguard Worker #endif // FCP_BASE_UNIQUE_VALUE_H_ 124