File indexing completed on 2025-04-04 08:33:22
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 #ifndef BOOST_OUTCOME_SYSTEM_ERROR2_RESULT_HPP
0032 #define BOOST_OUTCOME_SYSTEM_ERROR2_RESULT_HPP
0033
0034 #include "error.hpp"
0035
0036 #if __cplusplus >= 201703L || _HAS_CXX17
0037 #if __has_include(<variant>)
0038
0039 #include <exception>
0040 #include <variant>
0041
0042 BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
0043
0044 template <class T> inline constexpr std::in_place_type_t<T> in_place_type{};
0045
0046 template <class T> class result;
0047
0048
0049 template <class T> struct is_result : public std::false_type
0050 {
0051 };
0052 template <class T> struct is_result<result<T>> : public std::true_type
0053 {
0054 };
0055
0056
0057
0058 class bad_result_access : public std::exception
0059 {
0060 public:
0061 bad_result_access() = default;
0062
0063 virtual const char *what() const noexcept override { return "bad result access"; }
0064 };
0065
0066 namespace detail
0067 {
0068 struct void_
0069 {
0070 };
0071 template <class T> using devoid = std::conditional_t<std::is_void_v<T>, void_, T>;
0072 }
0073
0074
0075
0076
0077
0078
0079
0080 template <class T> class result : protected std::variant<BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::error, detail::devoid<T>>
0081 {
0082 using _base = std::variant<BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::error, detail::devoid<T>>;
0083 static_assert(!std::is_reference_v<T>, "Type cannot be a reference");
0084 static_assert(!std::is_array_v<T>, "Type cannot be an array");
0085 static_assert(!std::is_same_v<T, BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::error>, "Type cannot be a std::error");
0086
0087
0088 struct _implicit_converting_constructor_tag
0089 {
0090 };
0091 struct _explicit_converting_constructor_tag
0092 {
0093 };
0094 struct _implicit_constructor_tag
0095 {
0096 };
0097 struct _implicit_in_place_value_constructor_tag
0098 {
0099 };
0100 struct _implicit_in_place_error_constructor_tag
0101 {
0102 };
0103
0104 public:
0105
0106 using value_type = T;
0107
0108 using error_type = BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::error;
0109
0110 using value_type_if_enabled = detail::devoid<T>;
0111
0112 template <class U> using rebind = result<U>;
0113
0114 protected:
0115 constexpr void _check() const
0116 {
0117 if(_base::index() == 0)
0118 {
0119 std::get_if<0>(this)->throw_exception();
0120 }
0121 }
0122 constexpr
0123 #ifdef _MSC_VER
0124 __declspec(noreturn)
0125 #elif defined(__GNUC__) || defined(__clang__)
0126 __attribute__((noreturn))
0127 #endif
0128 void _ub()
0129 {
0130 assert(false);
0131 #if defined(__GNUC__) || defined(__clang__)
0132 __builtin_unreachable();
0133 #elif defined(_MSC_VER)
0134 __assume(0);
0135 #endif
0136 }
0137
0138 public:
0139 constexpr _base &_internal() noexcept { return *this; }
0140 constexpr const _base &_internal() const noexcept { return *this; }
0141
0142
0143 result() = delete;
0144
0145 result(const result &) = delete;
0146
0147 result(result &&) = default;
0148
0149 result &operator=(const result &) = delete;
0150
0151 result &operator=(result &&) = default;
0152
0153 ~result() = default;
0154
0155
0156 BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class U)
0157 BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(std::is_convertible_v<U, T>)) constexpr result(result<U> &&o, _implicit_converting_constructor_tag = {}) noexcept(std::is_nothrow_constructible_v<T, U>)
0158 : _base(std::move(o))
0159 {
0160 }
0161
0162 BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class U)
0163 BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(std::is_convertible_v<U, T>)) constexpr result(const result<U> &o, _implicit_converting_constructor_tag = {}) noexcept(std::is_nothrow_constructible_v<T, U>)
0164 : _base(o)
0165 {
0166 }
0167
0168 BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class U)
0169 BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(std::is_constructible_v<T, U>)) constexpr explicit result(result<U> &&o, _explicit_converting_constructor_tag = {}) noexcept(std::is_nothrow_constructible_v<T, U>)
0170 : _base(std::move(o))
0171 {
0172 }
0173
0174 BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class U)
0175 BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(std::is_constructible_v<T, U>)) constexpr explicit result(const result<U> &o, _explicit_converting_constructor_tag = {}) noexcept(std::is_nothrow_constructible_v<T, U>)
0176 : _base(o)
0177 {
0178 }
0179
0180
0181 using _base::_base;
0182
0183
0184 constexpr explicit result(std::in_place_type_t<void> ) noexcept
0185 : _base(in_place_type<detail::void_>)
0186 {
0187 }
0188
0189
0190 BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class Arg1, class Arg2, class... Args, long = 5)
0191 BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(!(std::is_constructible_v<value_type, Arg1, Arg2, Args...> && std::is_constructible_v<error_type, Arg1, Arg2, Args...>)
0192 &&std::is_constructible_v<error_type, Arg1, Arg2, Args...>))
0193 constexpr result(Arg1 &&arg1, Arg2 &&arg2, Args &&...args) noexcept(std::is_nothrow_constructible_v<error_type, Arg1, Arg2, Args...>)
0194 : _base(std::in_place_index<0>, std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Args>(args)...)
0195 {
0196 }
0197
0198
0199 BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class Arg1, class Arg2, class... Args, int = 5)
0200 BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(!(std::is_constructible_v<value_type, Arg1, Arg2, Args...> && std::is_constructible_v<error_type, Arg1, Arg2, Args...>)
0201 &&std::is_constructible_v<value_type, Arg1, Arg2, Args...>))
0202 constexpr result(Arg1 &&arg1, Arg2 &&arg2, Args &&...args) noexcept(std::is_nothrow_constructible_v<value_type, Arg1, Arg2, Args...>)
0203 : _base(std::in_place_index<1>, std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Args>(args)...)
0204 {
0205 }
0206
0207
0208 BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class U, class... Args,
0209 class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<U, Args...>::type)
0210 BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(!std::is_same<typename std::decay<U>::type, result>::value
0211 && !std::is_same<typename std::decay<U>::type, value_type>::value
0212 && is_status_code<MakeStatusCodeResult>::value
0213 && std::is_constructible<error_type, MakeStatusCodeResult>::value))
0214 constexpr result(U &&v, Args &&...args) noexcept(noexcept(make_status_code(std::declval<U>(), std::declval<Args>()...)))
0215 : _base(std::in_place_index<0>, make_status_code(static_cast<U &&>(v), static_cast<Args &&>(args)...))
0216 {
0217 }
0218
0219
0220 constexpr void swap(result &o) noexcept(std::is_nothrow_swappable_v<_base>) { _base::swap(o); }
0221
0222
0223 constexpr result clone() const { return has_value() ? result(value()) : result(error().clone()); }
0224
0225
0226 constexpr bool has_value() const noexcept { return _base::index() == 1; }
0227
0228 explicit operator bool() const noexcept { return has_value(); }
0229
0230 constexpr bool has_error() const noexcept { return _base::index() == 0; }
0231
0232
0233 constexpr value_type_if_enabled &value() &
0234 {
0235 _check();
0236 return std::get<1>(*this);
0237 }
0238
0239 constexpr const value_type_if_enabled &value() const &
0240 {
0241 _check();
0242 return std::get<1>(*this);
0243 }
0244
0245 constexpr value_type_if_enabled &&value() &&
0246 {
0247 _check();
0248 return std::get<1>(std::move(*this));
0249 }
0250
0251 constexpr const value_type_if_enabled &&value() const &&
0252 {
0253 _check();
0254 return std::get<1>(std::move(*this));
0255 }
0256
0257
0258 constexpr error_type &error() &
0259 {
0260 if(!has_error())
0261 {
0262 #ifndef BOOST_NO_EXCEPTIONS
0263 throw bad_result_access();
0264 #else
0265 abort();
0266 #endif
0267 }
0268 return *std::get_if<0>(this);
0269 }
0270
0271 constexpr const error_type &error() const &
0272 {
0273 if(!has_error())
0274 {
0275 #ifndef BOOST_NO_EXCEPTIONS
0276 throw bad_result_access();
0277 #else
0278 abort();
0279 #endif
0280 }
0281 return *std::get_if<0>(this);
0282 }
0283
0284 constexpr error_type &&error() &&
0285 {
0286 if(!has_error())
0287 {
0288 #ifndef BOOST_NO_EXCEPTIONS
0289 throw bad_result_access();
0290 #else
0291 abort();
0292 #endif
0293 }
0294 return std::move(*std::get_if<0>(this));
0295 }
0296
0297 constexpr const error_type &&error() const &&
0298 {
0299 if(!has_error())
0300 {
0301 #ifndef BOOST_NO_EXCEPTIONS
0302 throw bad_result_access();
0303 #else
0304 abort();
0305 #endif
0306 }
0307 return std::move(*std::get_if<0>(this));
0308 }
0309
0310
0311 constexpr value_type_if_enabled &assume_value() &noexcept
0312 {
0313 if(!has_value())
0314 {
0315 _ub();
0316 }
0317 return *std::get_if<1>(this);
0318 }
0319
0320 constexpr const value_type_if_enabled &assume_value() const &noexcept
0321 {
0322 if(!has_value())
0323 {
0324 _ub();
0325 }
0326 return *std::get_if<1>(this);
0327 }
0328
0329 constexpr value_type_if_enabled &&assume_value() &&noexcept
0330 {
0331 if(!has_value())
0332 {
0333 _ub();
0334 }
0335 return std::move(*std::get_if<1>(this));
0336 }
0337
0338 constexpr const value_type_if_enabled &&assume_value() const &&noexcept
0339 {
0340 if(!has_value())
0341 {
0342 _ub();
0343 }
0344 return std::move(*std::get_if<1>(this));
0345 }
0346
0347
0348 constexpr error_type &assume_error() &noexcept
0349 {
0350 if(!has_error())
0351 {
0352 _ub();
0353 }
0354 return *std::get_if<0>(this);
0355 }
0356
0357 constexpr const error_type &assume_error() const &noexcept
0358 {
0359 if(!has_error())
0360 {
0361 _ub();
0362 }
0363 return *std::get_if<0>(this);
0364 }
0365
0366 constexpr error_type &&assume_error() &&noexcept
0367 {
0368 if(!has_error())
0369 {
0370 _ub();
0371 }
0372 return std::move(*std::get_if<0>(this));
0373 }
0374
0375 constexpr const error_type &&assume_error() const &&noexcept
0376 {
0377 if(!has_error())
0378 {
0379 _ub();
0380 }
0381 return std::move(*std::get_if<0>(this));
0382 }
0383 };
0384
0385
0386 template <class T, class U, typename = decltype(std::declval<T>() == std::declval<U>())> constexpr inline bool operator==(const result<T> &a, const result<U> &b) noexcept
0387 {
0388 const auto &x = a._internal();
0389 return x == b;
0390 }
0391
0392 template <class T, class U, typename = decltype(std::declval<T>() != std::declval<U>())> constexpr inline bool operator!=(const result<T> &a, const result<U> &b) noexcept
0393 {
0394 const auto &x = a._internal();
0395 return x != b;
0396 }
0397
0398 BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
0399
0400 #endif
0401 #endif
0402 #endif