• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
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  * http://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 
16 #ifndef PANDA_LIBPANDABASE_UTILS_EXPECTED_H_
17 #define PANDA_LIBPANDABASE_UTILS_EXPECTED_H_
18 
19 #include <variant>
20 
21 #include "macros.h"
22 
23 namespace panda {
24 
25 template <class E>
26 class Unexpected final {
27 public:
Unexpected(E e)28     explicit Unexpected(E e) noexcept(std::is_nothrow_move_constructible_v<E>) : e_(std::move(e)) {}
29 
Value()30     const E &Value() const &noexcept
31     {
32         return e_;
33     }
Value()34     E &Value() & noexcept
35     {
36         return e_;
37     }
Value()38     E &&Value() && noexcept
39     {
40         return std::move(e_);
41     }
42 
43     ~Unexpected() = default;
44 
45     DEFAULT_COPY_SEMANTIC(Unexpected);
46     NO_MOVE_SEMANTIC(Unexpected);
47 
48 private:
49     E e_;
50 };
51 
52 class ExpectedConfig final {
53 public:
54 #ifdef NDEBUG
55     static constexpr bool RELEASE = true;
56 #else
57     static constexpr bool RELEASE = false;
58 #endif
59 };
60 
61 // Simplified implementation of proposed std::expected
62 // Note that as with std::expected, program that tries to instantiate
63 // Expected with T or E for a reference type is ill-formed.
64 template <class T, class E>
65 class Expected final {
66 public:
Expected()67     Expected() noexcept : v_(T()) {}
68     // The following constructors are non-explicit to be aligned with std::expected
69     // NOLINTNEXTLINE(google-explicit-constructor)
noexcept(std::is_nothrow_move_constructible_v<T>)70     Expected(T v) noexcept(std::is_nothrow_move_constructible_v<T>) : v_(std::move(v)) {}
71     // NOLINTNEXTLINE(google-explicit-constructor)
noexcept(std::is_nothrow_move_constructible_v<E>)72     Expected(Unexpected<E> e) noexcept(std::is_nothrow_move_constructible_v<E>) : v_(std::move(e.Value())) {}
73 
HasValue()74     bool HasValue() const noexcept
75     {
76         return std::holds_alternative<T>(v_);
77     }
78 
79     explicit operator bool() const noexcept
80     {
81         return HasValue();
82     }
83 
Error()84     const E &Error() const &noexcept(ExpectedConfig::RELEASE)
85     {
86         ASSERT(!HasValue());
87         return std::get<E>(v_);
88     }
89 
Error()90     E &Error() & noexcept(ExpectedConfig::RELEASE)
91     {
92         ASSERT(!HasValue());
93         return std::get<E>(v_);
94     }
95 
Error()96     E &&Error() && noexcept(ExpectedConfig::RELEASE)
97     {
98         ASSERT(!HasValue());
99         return std::move(std::get<E>(v_));
100     }
101 
Value()102     const T &Value() const &noexcept(ExpectedConfig::RELEASE)
103     {
104         ASSERT(HasValue());
105         return std::get<T>(v_);
106     }
107 
108     // NOLINTNEXTLINE(bugprone-exception-escape)
Value()109     T &Value() & noexcept(ExpectedConfig::RELEASE)
110     {
111         ASSERT(HasValue());
112         return std::get<T>(v_);
113     }
114 
Value()115     T &&Value() && noexcept(ExpectedConfig::RELEASE)
116     {
117         ASSERT(HasValue());
118         return std::move(std::get<T>(v_));
119     }
120 
noexcept(ExpectedConfig::RELEASE)121     const T &operator*() const &noexcept(ExpectedConfig::RELEASE)
122     {
123         return Value();
124     }
125 
noexcept(ExpectedConfig::RELEASE)126     T &operator*() & noexcept(ExpectedConfig::RELEASE)
127     {
128         return Value();
129     }
130 
noexcept(ExpectedConfig::RELEASE)131     T &&operator*() && noexcept(ExpectedConfig::RELEASE)
132     {
133         return std::move(*this).Value();
134     }
135 
136     template <class U = T>
ValueOr(U && v)137     T ValueOr(U &&v) const &
138     {
139         if (HasValue()) {
140             return Value();
141         }
142         return std::forward<U>(v);
143     }
144 
145     template <class U = T>
ValueOr(U && v)146     T ValueOr(U &&v) &&
147     {
148         if (HasValue()) {
149             return Value();
150         }
151         return std::forward<U>(v);
152     }
153 
154     ~Expected() = default;
155 
156     DEFAULT_COPY_SEMANTIC(Expected);
157     DEFAULT_MOVE_SEMANTIC(Expected);
158 
159 private:
160     std::variant<T, E> v_;
161 };
162 
163 }  // namespace panda
164 
165 #endif  // PANDA_LIBPANDABASE_UTILS_EXPECTED_H_
166