xref: /aosp_15_r20/external/emboss/runtime/cpp/emboss_maybe.h (revision 99e0aae7469b87d12f0ad23e61142c2d74c1ef70)
1 // Copyright 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // Definition of the Maybe<T> template class.
16 #ifndef EMBOSS_RUNTIME_CPP_EMBOSS_MAYBE_H_
17 #define EMBOSS_RUNTIME_CPP_EMBOSS_MAYBE_H_
18 
19 #include <utility>
20 
21 #include "runtime/cpp/emboss_defines.h"
22 
23 namespace emboss {
24 // TODO(bolms): Should Maybe be a public type (i.e., live in ::emboss)?
25 namespace support {
26 
27 // Maybe<T> is similar to, but much more restricted than, C++17's std::optional.
28 // It is intended for use in Emboss's expression system, wherein a non-Known()
29 // Maybe<T> will usually (but not always) poison the result of an operation.
30 //
31 // As such, Maybe<> is intended for use with small, copyable T's: specifically,
32 // integers, enums, and booleans.  It may not perform well with other types.
33 template <typename T>
34 class Maybe final {
35  public:
Maybe()36   constexpr Maybe() : value_(), known_(false) {}
Maybe(T value)37   constexpr explicit Maybe(T value)
38       : value_(::std::move(value)), known_(true) {}
39   constexpr Maybe(const Maybe<T> &) = default;
40   ~Maybe() = default;
41   Maybe &operator=(const Maybe &) = default;
42   Maybe &operator=(T value) {
43     value_ = ::std::move(value);
44     known_ = true;
45     return *this;
46   }
47   Maybe &operator=(const T &value) {
48     value_ = value;
49     known_ = true;
50     return *this;
51   }
52 
Known()53   constexpr bool Known() const { return known_; }
Value()54   T Value() const {
55     EMBOSS_CHECK(Known());
56     return value_;
57   }
ValueOr(T default_value)58   constexpr T ValueOr(T default_value) const {
59     return known_ ? value_ : default_value;
60   }
61   // A non-Ok() Maybe value-initializes value_ to a default (by explicitly
62   // calling the nullary constructor on value_ in the initializer list), so it
63   // is safe to just return value_ here.  For integral types and enums, value_
64   // will be 0, for bool it will be false, and for other types it depends on the
65   // constructor's behavior.
ValueOrDefault()66   constexpr T ValueOrDefault() const { return value_; }
67 
68  private:
69   T value_;
70   bool known_;
71 };
72 
73 }  // namespace support
74 }  // namespace emboss
75 
76 #endif  // EMBOSS_RUNTIME_CPP_EMBOSS_MAYBE_H_
77