File indexing completed on 2025-12-15 09:41:57
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
0032
0033
0034
0035 #ifndef ABSL_TYPES_OPTIONAL_H_
0036 #define ABSL_TYPES_OPTIONAL_H_
0037
0038 #include "absl/base/config.h" // TODO(calabrese) IWYU removal?
0039 #include "absl/utility/utility.h"
0040
0041 #ifdef ABSL_USES_STD_OPTIONAL
0042
0043 #include <optional> // IWYU pragma: export
0044
0045 namespace absl {
0046 ABSL_NAMESPACE_BEGIN
0047 using std::bad_optional_access;
0048 using std::optional;
0049 using std::make_optional;
0050 using std::nullopt_t;
0051 using std::nullopt;
0052 ABSL_NAMESPACE_END
0053 }
0054
0055 #else
0056
0057 #include <cassert>
0058 #include <functional>
0059 #include <initializer_list>
0060 #include <type_traits>
0061 #include <utility>
0062
0063 #include "absl/base/attributes.h"
0064 #include "absl/base/nullability.h"
0065 #include "absl/base/internal/inline_variable.h"
0066 #include "absl/meta/type_traits.h"
0067 #include "absl/types/bad_optional_access.h"
0068 #include "absl/types/internal/optional.h"
0069
0070 namespace absl {
0071 ABSL_NAMESPACE_BEGIN
0072
0073
0074
0075
0076
0077 struct nullopt_t {
0078
0079 explicit constexpr nullopt_t(optional_internal::init_t) noexcept {}
0080 };
0081
0082
0083
0084
0085
0086 ABSL_INTERNAL_INLINE_CONSTEXPR(nullopt_t, nullopt,
0087 nullopt_t(optional_internal::init_t()));
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119 template <typename T>
0120 class optional : private optional_internal::optional_data<T>,
0121 private optional_internal::optional_ctor_base<
0122 optional_internal::ctor_copy_traits<T>::traits>,
0123 private optional_internal::optional_assign_base<
0124 optional_internal::assign_copy_traits<T>::traits> {
0125 using data_base = optional_internal::optional_data<T>;
0126
0127 public:
0128 typedef T value_type;
0129
0130
0131
0132
0133
0134 constexpr optional() noexcept = default;
0135
0136
0137 constexpr optional(nullopt_t) noexcept {}
0138
0139
0140 optional(const optional&) = default;
0141
0142
0143 optional(optional&&) = default;
0144
0145
0146
0147
0148
0149 template <typename InPlaceT, typename... Args,
0150 absl::enable_if_t<absl::conjunction<
0151 std::is_same<InPlaceT, in_place_t>,
0152 std::is_constructible<T, Args&&...> >::value>* = nullptr>
0153 constexpr explicit optional(InPlaceT, Args&&... args)
0154 : data_base(in_place_t(), std::forward<Args>(args)...) {}
0155
0156
0157
0158
0159
0160 template <typename U, typename... Args,
0161 typename = typename std::enable_if<std::is_constructible<
0162 T, std::initializer_list<U>&, Args&&...>::value>::type>
0163 constexpr explicit optional(in_place_t, std::initializer_list<U> il,
0164 Args&&... args)
0165 : data_base(in_place_t(), il, std::forward<Args>(args)...) {}
0166
0167
0168 template <
0169 typename U = T,
0170 typename std::enable_if<
0171 absl::conjunction<absl::negation<std::is_same<
0172 in_place_t, typename std::decay<U>::type> >,
0173 absl::negation<std::is_same<
0174 optional<T>, typename std::decay<U>::type> >,
0175 std::is_convertible<U&&, T>,
0176 std::is_constructible<T, U&&> >::value,
0177 bool>::type = false>
0178 constexpr optional(U&& v) : data_base(in_place_t(), std::forward<U>(v)) {}
0179
0180
0181 template <
0182 typename U = T,
0183 typename std::enable_if<
0184 absl::conjunction<absl::negation<std::is_same<
0185 in_place_t, typename std::decay<U>::type> >,
0186 absl::negation<std::is_same<
0187 optional<T>, typename std::decay<U>::type> >,
0188 absl::negation<std::is_convertible<U&&, T> >,
0189 std::is_constructible<T, U&&> >::value,
0190 bool>::type = false>
0191 explicit constexpr optional(U&& v)
0192 : data_base(in_place_t(), std::forward<U>(v)) {}
0193
0194
0195 template <typename U,
0196 typename std::enable_if<
0197 absl::conjunction<
0198 absl::negation<std::is_same<T, U> >,
0199 std::is_constructible<T, const U&>,
0200 absl::negation<
0201 optional_internal::
0202 is_constructible_convertible_from_optional<T, U> >,
0203 std::is_convertible<const U&, T> >::value,
0204 bool>::type = false>
0205 optional(const optional<U>& rhs) {
0206 if (rhs) {
0207 this->construct(*rhs);
0208 }
0209 }
0210
0211
0212 template <typename U,
0213 typename std::enable_if<
0214 absl::conjunction<
0215 absl::negation<std::is_same<T, U>>,
0216 std::is_constructible<T, const U&>,
0217 absl::negation<
0218 optional_internal::
0219 is_constructible_convertible_from_optional<T, U>>,
0220 absl::negation<std::is_convertible<const U&, T>>>::value,
0221 bool>::type = false>
0222 explicit optional(const optional<U>& rhs) {
0223 if (rhs) {
0224 this->construct(*rhs);
0225 }
0226 }
0227
0228
0229 template <typename U,
0230 typename std::enable_if<
0231 absl::conjunction<
0232 absl::negation<std::is_same<T, U> >,
0233 std::is_constructible<T, U&&>,
0234 absl::negation<
0235 optional_internal::
0236 is_constructible_convertible_from_optional<T, U> >,
0237 std::is_convertible<U&&, T> >::value,
0238 bool>::type = false>
0239 optional(optional<U>&& rhs) {
0240 if (rhs) {
0241 this->construct(std::move(*rhs));
0242 }
0243 }
0244
0245
0246 template <
0247 typename U,
0248 typename std::enable_if<
0249 absl::conjunction<
0250 absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
0251 absl::negation<
0252 optional_internal::is_constructible_convertible_from_optional<
0253 T, U>>,
0254 absl::negation<std::is_convertible<U&&, T>>>::value,
0255 bool>::type = false>
0256 explicit optional(optional<U>&& rhs) {
0257 if (rhs) {
0258 this->construct(std::move(*rhs));
0259 }
0260 }
0261
0262
0263 ~optional() = default;
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273 optional& operator=(nullopt_t) noexcept {
0274 this->destruct();
0275 return *this;
0276 }
0277
0278
0279 optional& operator=(const optional& src) = default;
0280
0281
0282 optional& operator=(optional&& src) = default;
0283
0284
0285 template <typename U = T,
0286 int&...,
0287 typename = typename std::enable_if<absl::conjunction<
0288 absl::negation<
0289 std::is_same<optional<T>, typename std::decay<U>::type> >,
0290 absl::negation<absl::conjunction<
0291 std::is_scalar<T>,
0292 std::is_same<T, typename std::decay<U>::type> > >,
0293 std::is_constructible<T, U>,
0294 std::is_assignable<T&, U> >::value>::type>
0295 optional& operator=(U&& v) {
0296 this->assign(std::forward<U>(v));
0297 return *this;
0298 }
0299
0300 template <
0301 typename U,
0302 int&...,
0303 typename = typename std::enable_if<absl::conjunction<
0304 absl::negation<std::is_same<T, U> >,
0305 std::is_constructible<T, const U&>, std::is_assignable<T&, const U&>,
0306 absl::negation<
0307 optional_internal::
0308 is_constructible_convertible_assignable_from_optional<
0309 T, U> > >::value>::type>
0310 optional& operator=(const optional<U>& rhs) {
0311 if (rhs) {
0312 this->assign(*rhs);
0313 } else {
0314 this->destruct();
0315 }
0316 return *this;
0317 }
0318
0319 template <typename U,
0320 int&...,
0321 typename = typename std::enable_if<absl::conjunction<
0322 absl::negation<std::is_same<T, U> >,
0323 std::is_constructible<T, U>, std::is_assignable<T&, U>,
0324 absl::negation<
0325 optional_internal::
0326 is_constructible_convertible_assignable_from_optional<
0327 T, U> > >::value>::type>
0328 optional& operator=(optional<U>&& rhs) {
0329 if (rhs) {
0330 this->assign(std::move(*rhs));
0331 } else {
0332 this->destruct();
0333 }
0334 return *this;
0335 }
0336
0337
0338
0339
0340
0341
0342 ABSL_ATTRIBUTE_REINITIALIZES void reset() noexcept { this->destruct(); }
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357 template <typename... Args,
0358 typename = typename std::enable_if<
0359 std::is_constructible<T, Args&&...>::value>::type>
0360 T& emplace(Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0361 this->destruct();
0362 this->construct(std::forward<Args>(args)...);
0363 return reference();
0364 }
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377 template <typename U, typename... Args,
0378 typename = typename std::enable_if<std::is_constructible<
0379 T, std::initializer_list<U>&, Args&&...>::value>::type>
0380 T& emplace(std::initializer_list<U> il,
0381 Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0382 this->destruct();
0383 this->construct(il, std::forward<Args>(args)...);
0384 return reference();
0385 }
0386
0387
0388
0389
0390 void swap(optional& rhs) noexcept(
0391 std::is_nothrow_move_constructible<T>::value&&
0392 type_traits_internal::IsNothrowSwappable<T>::value) {
0393 if (*this) {
0394 if (rhs) {
0395 type_traits_internal::Swap(**this, *rhs);
0396 } else {
0397 rhs.construct(std::move(**this));
0398 this->destruct();
0399 }
0400 } else {
0401 if (rhs) {
0402 this->construct(std::move(*rhs));
0403 rhs.destruct();
0404 } else {
0405
0406 }
0407 }
0408 }
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418 absl::Nonnull<const T*> operator->() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
0419 ABSL_HARDENING_ASSERT(this->engaged_);
0420 return std::addressof(this->data_);
0421 }
0422 absl::Nonnull<T*> operator->() ABSL_ATTRIBUTE_LIFETIME_BOUND {
0423 ABSL_HARDENING_ASSERT(this->engaged_);
0424 return std::addressof(this->data_);
0425 }
0426
0427
0428
0429
0430
0431 constexpr const T& operator*() const& ABSL_ATTRIBUTE_LIFETIME_BOUND {
0432 return ABSL_HARDENING_ASSERT(this->engaged_), reference();
0433 }
0434 T& operator*() & ABSL_ATTRIBUTE_LIFETIME_BOUND {
0435 ABSL_HARDENING_ASSERT(this->engaged_);
0436 return reference();
0437 }
0438 constexpr const T&& operator*() const&& ABSL_ATTRIBUTE_LIFETIME_BOUND {
0439 return ABSL_HARDENING_ASSERT(this->engaged_), std::move(reference());
0440 }
0441 T&& operator*() && ABSL_ATTRIBUTE_LIFETIME_BOUND {
0442 ABSL_HARDENING_ASSERT(this->engaged_);
0443 return std::move(reference());
0444 }
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456 constexpr explicit operator bool() const noexcept { return this->engaged_; }
0457
0458
0459
0460
0461
0462 constexpr bool has_value() const noexcept { return this->engaged_; }
0463
0464
0465
0466 #ifdef _MSC_VER
0467 #pragma warning(push)
0468 #pragma warning(disable : 4702)
0469 #endif
0470
0471
0472
0473
0474
0475
0476 constexpr const T& value() const& ABSL_ATTRIBUTE_LIFETIME_BOUND {
0477 return static_cast<bool>(*this)
0478 ? reference()
0479 : (optional_internal::throw_bad_optional_access(), reference());
0480 }
0481 T& value() & ABSL_ATTRIBUTE_LIFETIME_BOUND {
0482 return static_cast<bool>(*this)
0483 ? reference()
0484 : (optional_internal::throw_bad_optional_access(), reference());
0485 }
0486 T&& value() && ABSL_ATTRIBUTE_LIFETIME_BOUND {
0487 return std::move(
0488 static_cast<bool>(*this)
0489 ? reference()
0490 : (optional_internal::throw_bad_optional_access(), reference()));
0491 }
0492 constexpr const T&& value()
0493 const&& ABSL_ATTRIBUTE_LIFETIME_BOUND {
0494 return std::move(
0495 static_cast<bool>(*this)
0496 ? reference()
0497 : (optional_internal::throw_bad_optional_access(), reference()));
0498 }
0499 #ifdef _MSC_VER
0500 #pragma warning(pop)
0501 #endif
0502
0503
0504
0505
0506
0507 template <typename U>
0508 constexpr T value_or(U&& v) const& {
0509 static_assert(std::is_copy_constructible<value_type>::value,
0510 "optional<T>::value_or: T must be copy constructible");
0511 static_assert(std::is_convertible<U&&, value_type>::value,
0512 "optional<T>::value_or: U must be convertible to T");
0513 return static_cast<bool>(*this) ? **this
0514 : static_cast<T>(std::forward<U>(v));
0515 }
0516 template <typename U>
0517 T value_or(U&& v) && {
0518 static_assert(std::is_move_constructible<value_type>::value,
0519 "optional<T>::value_or: T must be move constructible");
0520 static_assert(std::is_convertible<U&&, value_type>::value,
0521 "optional<T>::value_or: U must be convertible to T");
0522 return static_cast<bool>(*this) ? std::move(**this)
0523 : static_cast<T>(std::forward<U>(v));
0524 }
0525
0526 private:
0527
0528 constexpr const T& reference() const { return this->data_; }
0529 T& reference() { return this->data_; }
0530
0531
0532
0533 static_assert(
0534 !std::is_same<nullopt_t, typename std::remove_cv<T>::type>::value,
0535 "optional<nullopt_t> is not allowed.");
0536 static_assert(
0537 !std::is_same<in_place_t, typename std::remove_cv<T>::type>::value,
0538 "optional<in_place_t> is not allowed.");
0539 static_assert(!std::is_reference<T>::value,
0540 "optional<reference> is not allowed.");
0541 };
0542
0543
0544
0545
0546
0547
0548
0549 template <typename T, typename std::enable_if<
0550 std::is_move_constructible<T>::value &&
0551 type_traits_internal::IsSwappable<T>::value,
0552 bool>::type = false>
0553 void swap(optional<T>& a, optional<T>& b) noexcept(noexcept(a.swap(b))) {
0554 a.swap(b);
0555 }
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572 template <typename T>
0573 constexpr optional<typename std::decay<T>::type> make_optional(T&& v) {
0574 return optional<typename std::decay<T>::type>(std::forward<T>(v));
0575 }
0576
0577 template <typename T, typename... Args>
0578 constexpr optional<T> make_optional(Args&&... args) {
0579 return optional<T>(in_place_t(), std::forward<Args>(args)...);
0580 }
0581
0582 template <typename T, typename U, typename... Args>
0583 constexpr optional<T> make_optional(std::initializer_list<U> il,
0584 Args&&... args) {
0585 return optional<T>(in_place_t(), il, std::forward<Args>(args)...);
0586 }
0587
0588
0589
0590
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602 template <typename T, typename U>
0603 constexpr auto operator==(const optional<T>& x, const optional<U>& y)
0604 -> decltype(optional_internal::convertible_to_bool(*x == *y)) {
0605 return static_cast<bool>(x) != static_cast<bool>(y)
0606 ? false
0607 : static_cast<bool>(x) == false ? true
0608 : static_cast<bool>(*x == *y);
0609 }
0610
0611
0612
0613 template <typename T, typename U>
0614 constexpr auto operator!=(const optional<T>& x, const optional<U>& y)
0615 -> decltype(optional_internal::convertible_to_bool(*x != *y)) {
0616 return static_cast<bool>(x) != static_cast<bool>(y)
0617 ? true
0618 : static_cast<bool>(x) == false ? false
0619 : static_cast<bool>(*x != *y);
0620 }
0621
0622 template <typename T, typename U>
0623 constexpr auto operator<(const optional<T>& x, const optional<U>& y)
0624 -> decltype(optional_internal::convertible_to_bool(*x < *y)) {
0625 return !y ? false : !x ? true : static_cast<bool>(*x < *y);
0626 }
0627
0628 template <typename T, typename U>
0629 constexpr auto operator>(const optional<T>& x, const optional<U>& y)
0630 -> decltype(optional_internal::convertible_to_bool(*x > *y)) {
0631 return !x ? false : !y ? true : static_cast<bool>(*x > *y);
0632 }
0633
0634 template <typename T, typename U>
0635 constexpr auto operator<=(const optional<T>& x, const optional<U>& y)
0636 -> decltype(optional_internal::convertible_to_bool(*x <= *y)) {
0637 return !x ? true : !y ? false : static_cast<bool>(*x <= *y);
0638 }
0639
0640 template <typename T, typename U>
0641 constexpr auto operator>=(const optional<T>& x, const optional<U>& y)
0642 -> decltype(optional_internal::convertible_to_bool(*x >= *y)) {
0643 return !y ? true : !x ? false : static_cast<bool>(*x >= *y);
0644 }
0645
0646
0647
0648 template <typename T>
0649 constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept {
0650 return !x;
0651 }
0652 template <typename T>
0653 constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept {
0654 return !x;
0655 }
0656 template <typename T>
0657 constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept {
0658 return static_cast<bool>(x);
0659 }
0660 template <typename T>
0661 constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept {
0662 return static_cast<bool>(x);
0663 }
0664 template <typename T>
0665 constexpr bool operator<(const optional<T>&, nullopt_t) noexcept {
0666 return false;
0667 }
0668 template <typename T>
0669 constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept {
0670 return static_cast<bool>(x);
0671 }
0672 template <typename T>
0673 constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept {
0674 return !x;
0675 }
0676 template <typename T>
0677 constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept {
0678 return true;
0679 }
0680 template <typename T>
0681 constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept {
0682 return static_cast<bool>(x);
0683 }
0684 template <typename T>
0685 constexpr bool operator>(nullopt_t, const optional<T>&) noexcept {
0686 return false;
0687 }
0688 template <typename T>
0689 constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept {
0690 return true;
0691 }
0692 template <typename T>
0693 constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept {
0694 return !x;
0695 }
0696
0697
0698
0699
0700
0701
0702 template <typename T, typename U>
0703 constexpr auto operator==(const optional<T>& x, const U& v)
0704 -> decltype(optional_internal::convertible_to_bool(*x == v)) {
0705 return static_cast<bool>(x) ? static_cast<bool>(*x == v) : false;
0706 }
0707 template <typename T, typename U>
0708 constexpr auto operator==(const U& v, const optional<T>& x)
0709 -> decltype(optional_internal::convertible_to_bool(v == *x)) {
0710 return static_cast<bool>(x) ? static_cast<bool>(v == *x) : false;
0711 }
0712 template <typename T, typename U>
0713 constexpr auto operator!=(const optional<T>& x, const U& v)
0714 -> decltype(optional_internal::convertible_to_bool(*x != v)) {
0715 return static_cast<bool>(x) ? static_cast<bool>(*x != v) : true;
0716 }
0717 template <typename T, typename U>
0718 constexpr auto operator!=(const U& v, const optional<T>& x)
0719 -> decltype(optional_internal::convertible_to_bool(v != *x)) {
0720 return static_cast<bool>(x) ? static_cast<bool>(v != *x) : true;
0721 }
0722 template <typename T, typename U>
0723 constexpr auto operator<(const optional<T>& x, const U& v)
0724 -> decltype(optional_internal::convertible_to_bool(*x < v)) {
0725 return static_cast<bool>(x) ? static_cast<bool>(*x < v) : true;
0726 }
0727 template <typename T, typename U>
0728 constexpr auto operator<(const U& v, const optional<T>& x)
0729 -> decltype(optional_internal::convertible_to_bool(v < *x)) {
0730 return static_cast<bool>(x) ? static_cast<bool>(v < *x) : false;
0731 }
0732 template <typename T, typename U>
0733 constexpr auto operator<=(const optional<T>& x, const U& v)
0734 -> decltype(optional_internal::convertible_to_bool(*x <= v)) {
0735 return static_cast<bool>(x) ? static_cast<bool>(*x <= v) : true;
0736 }
0737 template <typename T, typename U>
0738 constexpr auto operator<=(const U& v, const optional<T>& x)
0739 -> decltype(optional_internal::convertible_to_bool(v <= *x)) {
0740 return static_cast<bool>(x) ? static_cast<bool>(v <= *x) : false;
0741 }
0742 template <typename T, typename U>
0743 constexpr auto operator>(const optional<T>& x, const U& v)
0744 -> decltype(optional_internal::convertible_to_bool(*x > v)) {
0745 return static_cast<bool>(x) ? static_cast<bool>(*x > v) : false;
0746 }
0747 template <typename T, typename U>
0748 constexpr auto operator>(const U& v, const optional<T>& x)
0749 -> decltype(optional_internal::convertible_to_bool(v > *x)) {
0750 return static_cast<bool>(x) ? static_cast<bool>(v > *x) : true;
0751 }
0752 template <typename T, typename U>
0753 constexpr auto operator>=(const optional<T>& x, const U& v)
0754 -> decltype(optional_internal::convertible_to_bool(*x >= v)) {
0755 return static_cast<bool>(x) ? static_cast<bool>(*x >= v) : false;
0756 }
0757 template <typename T, typename U>
0758 constexpr auto operator>=(const U& v, const optional<T>& x)
0759 -> decltype(optional_internal::convertible_to_bool(v >= *x)) {
0760 return static_cast<bool>(x) ? static_cast<bool>(v >= *x) : true;
0761 }
0762
0763 ABSL_NAMESPACE_END
0764 }
0765
0766 namespace std {
0767
0768
0769 template <typename T>
0770 struct hash<absl::optional<T> >
0771 : absl::optional_internal::optional_hash_base<T> {};
0772
0773 }
0774
0775 #undef ABSL_MSVC_CONSTEXPR_BUG_IN_UNION_LIKE_CLASS
0776
0777 #endif
0778
0779 #endif