GaitGeneration by Graph Search
読み取り中…
検索中…
一致する文字列を見つけられません
my_expected.h
[詳解]
1
3
4// Copyright(c) 2023-2025 Design Engineering Laboratory, Saitama University
5// Released under the MIT license
6// https://opensource.org/licenses/mit-license.php
7
8#ifndef DESIGNLAB_MY_EXPECTED_H_
9#define DESIGNLAB_MY_EXPECTED_H_
10
11#include <functional>
12#include <optional>
13#include <stdexcept>
14#include <type_traits>
15#include <utility>
16#include <variant>
17
18#include "my_expected_concept.h"
19#include "my_unexpected.h"
20
21namespace designlab::nostd {
22
23// 自作の例外 bad_expected_access
24class bad_expected_access : public std::exception {
25 public:
26 explicit bad_expected_access(const std::string& msg) : message_(msg) {}
27 explicit bad_expected_access(const char* msg) : message_(msg) {}
28
29 const char* what() const noexcept override { return message_.c_str(); }
30
31 private:
32 std::string message_;
33};
34
35template <class T, class W>
36constexpr bool converts_from_any_cvref = std::disjunction_v<
37 std::is_constructible<T, W&>, std::is_convertible<W&, T>,
38 std::is_constructible<T, W>, std::is_convertible<W, T>,
39 std::is_constructible<T, const W&>, std::is_convertible<const W&, T>,
40 std::is_constructible<T, const W>, std::is_convertible<const W, T>>;
41
45template <impl::IsExpected T, typename E>
46class expected final {
47 public:
48 using value_type = T;
49 using error_type = E;
51
54 constexpr expected()
55 requires std::is_default_constructible_v<T>
56 : storage_(T{}), has_value_(true) {}
57
58 constexpr expected(const expected& rhs)
59 : storage_(rhs.storage_), has_value_(rhs.has_value_) {}
60
61 constexpr expected(expected&& rhs) noexcept
62 requires(std::is_move_constructible_v<T> && std::is_move_constructible_v<E>)
63 : storage_(std::move(rhs.storage_)), has_value_(rhs.has_value_) {}
64
65 template <class U, class G>
66 constexpr expected(const expected<U, G>& rhs)
67 requires(std::is_constructible_v<T, const U&> &&
68 std::is_constructible_v<E, const G&> &&
69 !converts_from_any_cvref<T, expected<U, G>&> &&
70 !std::is_constructible_v<unexpected<E>, expected<U, G>&> &&
71 !std::is_constructible_v<unexpected<E>, expected<U, G>> &&
72 !std::is_constructible_v<unexpected<E>, const expected<U, G>&> &&
73 !std::is_constructible_v<unexpected<E>, const expected<U, G>>)
74 : storage_(rhs.storage_), has_value_(rhs.has_value_) {}
75
76 template <class U, class G>
77 constexpr expected(const expected<U, G>&& rhs) noexcept
78 requires(std::is_constructible_v<T, U> && std::is_constructible_v<E, G> &&
79 !converts_from_any_cvref<T, expected<U, G>> &&
80 !std::is_constructible_v<unexpected<E>, expected<U, G>&> &&
81 !std::is_constructible_v<unexpected<E>, expected<U, G>> &&
82 !std::is_constructible_v<unexpected<E>, const expected<U, G>&> &&
83 !std::is_constructible_v<unexpected<E>, const expected<U, G>>)
84 : storage_(std::move(rhs.storage_)), has_value_(rhs.has_value_) {}
85
86 template <class U = T>
87 constexpr expected(U&& v)
88 requires(std::is_constructible_v<T, U> &&
89 !std::is_same_v<expected, std::remove_cvref_t<U>> &&
90 !std::is_same_v<std::remove_cvref_t<U>, std::in_place_t>)
91 : storage_(v), has_value_(true) {}
92
93 template <class G>
94 constexpr expected(const unexpected<G>& e)
95 : storage_(unexpected(e.error())), has_value_(false) {}
96
97 constexpr ~expected() = default;
98
101 constexpr const T* operator->() const noexcept {
102 return std::addressof(std::get<T>(storage_));
103 }
104
107 constexpr T* operator->() noexcept {
108 return std::addressof(std::get<T>(storage_));
109 }
110
113 constexpr const T& operator*() const& noexcept {
114 return std::get<T>(storage_);
115 }
116
119 constexpr T& operator*() & noexcept { return std::get<T>(storage_); }
120
121 constexpr explicit operator bool() const noexcept { return has_value_; }
122
124 constexpr bool has_value() const noexcept { return has_value_; }
125
129 constexpr const T& value() const {
130 if (!has_value_) throw bad_expected_access("no value present");
131 return std::get<T>(storage_);
132 }
133
137 constexpr T& value() {
138 if (!has_value_) throw bad_expected_access("no value present");
139 return std::get<T>(storage_);
140 }
141
145 constexpr const E& error() const {
146 if (has_value_) throw bad_expected_access("no error present");
147 auto& unexpected_value = std::get<unexpected<E>>(storage_);
148 return unexpected_value.error();
149 }
150
154 constexpr E& error() {
155 if (has_value_) throw bad_expected_access("no error present");
156 auto& unexpected_value = std::get<unexpected<E>>(storage_);
157 return unexpected_value.error();
158 }
159
160 template <class U>
161 constexpr T value_or(U&& v) const&
162 requires(std::is_constructible_v<T, U> && std::is_copy_constructible_v<T>)
163 {
164 return has_value() ? **this : static_cast<T>(std::forward<U>(v));
165 }
166
167 template <class G = E>
168 constexpr E error_or(G&& e) const&
169 requires(std::is_constructible_v<E, G> && std::is_copy_constructible_v<E>)
170 {
171 return has_value() ? std::forward<G>(e) : error();
172 }
173
174 // Monadic operations
175 template <class Return>
177 const std::function<expected<Return, E>(T)>& func) const& {
178 using ReturnType = expected<Return, E>;
179 if (has_value_) {
180 return ReturnType{func(value())};
181 } else {
182 return ReturnType{unexpected(error())};
183 }
184 }
185
186 template <class Func, class Ret = std::invoke_result_t<Func, T>>
187 constexpr auto and_then(Func&& func) const&
188 requires(std::is_invocable_r_v<Ret, Func, T> &&
189 std::is_same_v<typename Ret::error_type, E> &&
190 std::is_same_v<std::remove_cvref_t<Ret>,
192 {
193 using ReturnType = std::invoke_result_t<Func, T>;
194 if (has_value_) {
195 return ReturnType{func(value())};
196 } else {
197 return ReturnType{unexpected(error())};
198 }
199 }
200
201 private:
202 std::variant<T, unexpected<E>> storage_;
203 bool has_value_;
204};
205
206} // namespace designlab::nostd
207
208#endif // DESIGNLAB_MY_EXPECTED_H_
bad_expected_access(const std::string &msg)
Definition my_expected.h:26
const char * what() const noexcept override
Definition my_expected.h:29
自作の expected クラス
Definition my_expected.h:46
constexpr expected(const expected< U, G > &rhs)
Definition my_expected.h:66
constexpr bool has_value() const noexcept
正常値を持っている場合に true を返す.
constexpr E & error()
失敗時の値を返す.
constexpr const E & error() const
失敗時の値を返す.
constexpr const T & value() const
正常値を返す.
constexpr auto and_then(Func &&func) const &
constexpr expected(expected &&rhs) noexcept
Definition my_expected.h:61
constexpr expected(const expected< U, G > &&rhs) noexcept
Definition my_expected.h:77
constexpr expected(U &&v)
Definition my_expected.h:87
constexpr const T * operator->() const noexcept
正常値のポインタを返す.
constexpr expected(const unexpected< G > &e)
Definition my_expected.h:94
constexpr T & operator*() &noexcept
正常値を参照する.
constexpr expected(const expected &rhs)
Definition my_expected.h:58
constexpr expected< Return, E > and_then(const std::function< expected< Return, E >(T)> &func) const &
constexpr expected()
デフォルトコンストラクタ
Definition my_expected.h:54
constexpr const T & operator*() const &noexcept
正常値を参照する.
constexpr T value_or(U &&v) const &
constexpr E error_or(G &&e) const &
constexpr T * operator->() noexcept
正常値のポインタを返す.
constexpr T & value()
正常値を返す.
constexpr ~expected()=default
デストラクタ
constexpr bool converts_from_any_cvref
Definition my_expected.h:36
Definition com_type.h:21