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