xref: /aosp_15_r20/external/federated-compute/fcp/base/unique_value.h (revision 14675a029014e728ec732f129a32e299b2da0601)
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 Worker constexpr 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