9 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
10 #include <type_traits>
15 #if __cplusplus >= 201103L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201103L)
16 #define CONSTEXPR constexpr
23 #if __cplusplus >= 201103L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201103L)
24 #define NOEXCEPT(Expr) noexcept(Expr)
26 #define NOEXCEPT(Expr)
48 const nullopt_t nullopt(0);
62 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
63 template <
class... Args>
65 : is_populated_(
true), value_(std::forward<Args>(args)...) {}
68 : is_populated_(
true), value_(_value) {}
86 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
87 template <
class... Args>
88 void Init(Args&&... args) {
89 ::new (&value_) T(std::forward<Args>(args)...);
93 void Init(
const T& _value) {
94 ::new (&value_) T(_value);
117 template <
typename T>
131 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
132 template <
class... Args>
145 if (other.is_populated_)
149 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
151 if (other.is_populated_)
152 Init(std::move(other.value_));
159 template <
typename T>
167 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
170 template <
class... Args>
172 : storage_(in_place, std::forward<Args>(args)...) {}
175 : storage_(in_place, _value) {}
179 template <
typename U>
181 if (other.storage_.is_populated_)
182 storage_.Init(other.storage_.value_);
185 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
186 template <
typename U>
188 if (other.storage_.is_populated_)
189 storage_.Init(std::move(other.storage_.value_));
200 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
202 std::is_nothrow_move_assignable<T>::value &&
203 std::is_nothrow_move_constructible<T>::value) {
204 MoveAssign(std::move(other));
209 template <
typename U>
211 if (other.storage_.is_populated_)
212 InitOrAssign(other.storage_.value_);
217 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
218 template <
typename U>
220 if (other.storage_.is_populated_)
221 InitOrAssign(std::move(other.storage_.value_));
227 template <
typename U>
228 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
229 void InitOrAssign(U&& value) {
230 if (storage_.is_populated_)
231 storage_.value_ = std::forward<U>(value);
233 storage_.Init(std::forward<U>(value));
236 void InitOrAssign(
const U& value) {
237 if (storage_.is_populated_)
238 storage_.value_ = value;
240 storage_.Init(value);
245 void FreeIfNeeded() {
246 if (!storage_.is_populated_)
248 storage_.value_.~T();
249 storage_.is_populated_ =
false;
254 template <
typename U>
264 template <
bool is_copy_constructible>
271 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
279 template <
bool is_move_constructible>
287 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
294 template <
bool is_copy_assignable>
301 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
309 template <
bool is_move_assignable>
317 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
325 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
327 template <
typename T,
typename U>
328 struct IsConvertibleFromOptional
329 : std::integral_constant<
331 std::is_constructible<T, Optional<U>&>::value ||
332 std::is_constructible<T, const Optional<U>&>::value ||
333 std::is_constructible<T, Optional<U>&&>::value ||
334 std::is_constructible<T, const Optional<U>&&>::value ||
335 std::is_convertible<Optional<U>&, T>::value ||
336 std::is_convertible<const Optional<U>&, T>::value ||
337 std::is_convertible<Optional<U>&&, T>::value ||
338 std::is_convertible<const Optional<U>&&, T>::value> {};
340 template <
typename T,
typename U>
341 struct IsAssignableFromOptional
342 : std::integral_constant<
344 IsConvertibleFromOptional<T, U>::value ||
345 std::is_assignable<T&, Optional<U>&>::value ||
346 std::is_assignable<T&, const Optional<U>&>::value ||
347 std::is_assignable<T&, Optional<U>&&>::value ||
348 std::is_assignable<T&, const Optional<U>&&>::value> {};
352 namespace swappable_impl {
355 struct IsSwappableImpl {
359 template <
typename T>
360 static auto Check(
int)
361 -> decltype(swap(std::declval<T>(), std::declval<T>()), std::true_type());
363 template <
typename T>
364 static std::false_type Check(...);
367 template <
typename T>
368 struct IsSwappable : decltype(swappable_impl::IsSwappableImpl::Check<T&>(0)) {};
378 #define OPTIONAL_DECLSPEC_EMPTY_BASES __declspec(empty_bases)
380 #define OPTIONAL_DECLSPEC_EMPTY_BASES
402 template <
typename T>
403 class OPTIONAL_DECLSPEC_EMPTY_BASES Optional
404 :
public internal::OptionalBase<T>
405 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
406 ,
public internal::CopyConstructible<std::is_copy_constructible<T>::value>,
407 public internal::MoveConstructible<std::is_move_constructible<T>::value>,
408 public internal::CopyAssignable<std::is_copy_constructible<T>::value &&
409 std::is_copy_assignable<T>::value>,
410 public internal::MoveAssignable<std::is_move_constructible<T>::value &&
411 std::is_move_assignable<T>::value>
415 #undef OPTIONAL_DECLSPEC_EMPTY_BASES
417 typedef T value_type;
420 CONSTEXPR Optional() {}
421 CONSTEXPR Optional(
const Optional& other) : internal::OptionalBase<T>(other) {}
423 CONSTEXPR Optional(nullopt_t) {}
429 template <
typename U>
430 Optional(
const Optional<U>& other) : internal::OptionalBase<T>(other) {}
432 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
435 template <
typename U>
436 Optional(Optional<U>&& other) : internal::OptionalBase<T>(std::move(other)) {}
438 template <
class... Args>
439 CONSTEXPR
explicit Optional(in_place_t, Args&&... args)
440 : internal::OptionalBase<T>(in_place, std::forward<Args>(args)...) {}
442 template <
class U,
class... Args>
443 CONSTEXPR
explicit Optional(in_place_t,
444 std::initializer_list<U> il,
446 : internal::OptionalBase<T>(in_place, il, std::forward<Args>(args)...) {}
448 CONSTEXPR
explicit Optional(in_place_t,
const T& _value)
449 : internal::OptionalBase<T>(in_place, _value) {}
451 CONSTEXPR
explicit Optional(in_place_t,
454 : internal::OptionalBase<T>(in_place, il, _value) {}
459 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
460 template <
typename U = value_type>
461 CONSTEXPR Optional(U&& value)
462 : internal::OptionalBase<T>(in_place, std::forward<U>(value)) {}
464 template <
typename U>
465 CONSTEXPR Optional(
const U& value)
466 : internal::OptionalBase<T>(in_place, value) {}
472 Optional& operator=(
const Optional& other) {
473 if (&other ==
this) {
477 internal::OptionalBase<T>::operator=(other);
481 Optional& operator=(nullopt_t) {
487 template <
typename U>
488 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
489 Optional& operator=(U&& value) {
490 InitOrAssign(std::forward<U>(value));
494 Optional& operator=(
const U& value) {
501 template <
typename U>
502 Optional& operator=(
const Optional<U>& other) {
507 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
509 template <
typename U>
510 Optional& operator=(Optional<U>&& other) {
511 MoveAssign(std::move(other));
516 const T* operator->()
const {
517 return &storage_.value_;
520 const T& operator*()
const {
521 return storage_.value_;
525 return storage_.value_;
529 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
530 CONSTEXPR
explicit operator bool()
const {
return storage_.is_populated_; }
532 CONSTEXPR
operator bool()
const {
return storage_.is_populated_; }
535 CONSTEXPR
bool has_value()
const {
return storage_.is_populated_; }
538 const T& value()
const {
539 return storage_.value_;
543 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
544 CONSTEXPR T value_or(U&& default_value)
const {
548 static_assert(std::is_convertible<U, T>::value,
549 "U must be convertible to T");
550 return storage_.is_populated_
552 : static_cast<T>(std::forward<U>(default_value));
555 CONSTEXPR T value_or(
const U& default_value)
const {
556 return storage_.is_populated_
558 : static_cast<T>(default_value);
562 const T& value() const & {
563 return storage_.value_;
566 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
567 const T&& value() const && {
568 return std::move(storage_.value_);
573 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
574 CONSTEXPR T value_or(U&& default_value)
const & {
578 static_assert(std::is_convertible<U, T>::value,
579 "U must be convertible to T");
580 return storage_.is_populated_
582 : static_cast<T>(std::forward<U>(default_value));
585 CONSTEXPR T value_or(
const U& default_value)
const & {
589 static_assert(std::is_convertible<U, T>::value,
590 "U must be convertible to T");
591 return storage_.is_populated_
593 : static_cast<T>(default_value);
598 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
599 CONSTEXPR T value_or(U&& default_value)
const && {
603 static_assert(std::is_convertible<U, T>::value,
604 "U must be convertible to T");
605 return storage_.is_populated_
607 : static_cast<T>(std::forward<U>(default_value));
612 void swap(Optional& other) {
613 if (!storage_.is_populated_ && !other.storage_.is_populated_)
616 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
617 if (storage_.is_populated_ != other.storage_.is_populated_) {
618 if (storage_.is_populated_) {
619 other.storage_.Init(std::move(storage_.value_));
622 storage_.Init(std::move(other.storage_.value_));
623 other.FreeIfNeeded();
629 swap(**
this, *other);
632 void reset() { FreeIfNeeded(); }
634 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
635 template <
class... Args>
636 T& emplace(Args&&... args) {
638 storage_.Init(std::forward<Args>(args)...);
639 return storage_.value_;
642 template <
class U,
class... Args>
643 T& emplace(std::initializer_list<U> il, Args&&... args) {
645 storage_.Init(il, std::forward<Args>(args)...);
646 return storage_.value_;
649 T& emplace(
const T& _value) {
651 storage_.Init(_value);
652 return storage_.value_;
655 T& emplace(
const U il[],
const T& _value) {
657 storage_.Init(il, _value);
658 return storage_.value_;
665 using internal::OptionalBase<T>::CopyAssign;
666 using internal::OptionalBase<T>::FreeIfNeeded;
667 using internal::OptionalBase<T>::InitOrAssign;
668 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
669 using internal::OptionalBase<T>::MoveAssign;
671 using internal::OptionalBase<T>::storage_;
678 template <
class T,
class U>
679 bool operator==(
const Optional<T>& lhs,
const Optional<U>& rhs) {
680 if (lhs.has_value() != rhs.has_value())
682 if (!lhs.has_value())
687 template <
class T,
class U>
688 bool operator!=(
const Optional<T>& lhs,
const Optional<U>& rhs) {
689 if (lhs.has_value() != rhs.has_value())
691 if (!lhs.has_value())
696 template <
class T,
class U>
697 bool operator<(
const Optional<T>& lhs,
const Optional<U>& rhs) {
698 if (!rhs.has_value())
700 if (!lhs.has_value())
705 template <
class T,
class U>
706 bool operator<=(
const Optional<T>& lhs,
const Optional<U>& rhs) {
707 if (!lhs.has_value())
709 if (!rhs.has_value())
714 template <
class T,
class U>
715 bool operator>(
const Optional<T>& lhs,
const Optional<U>& rhs) {
716 if (!lhs.has_value())
718 if (!rhs.has_value())
723 template <
class T,
class U>
724 bool operator>=(
const Optional<T>& lhs,
const Optional<U>& rhs) {
725 if (!rhs.has_value())
727 if (!lhs.has_value())
733 CONSTEXPR
bool operator==(
const Optional<T>& opt, nullopt_t) {
738 CONSTEXPR
bool operator==(nullopt_t,
const Optional<T>& opt) {
743 CONSTEXPR
bool operator!=(
const Optional<T>& opt, nullopt_t) {
744 return opt.has_value();
748 CONSTEXPR
bool operator!=(nullopt_t,
const Optional<T>& opt) {
749 return opt.has_value();
753 CONSTEXPR
bool operator<(
const Optional<T>& opt, nullopt_t) {
758 CONSTEXPR
bool operator<(nullopt_t,
const Optional<T>& opt) {
759 return opt.has_value();
763 CONSTEXPR
bool operator<=(
const Optional<T>& opt, nullopt_t) {
768 CONSTEXPR
bool operator<=(nullopt_t,
const Optional<T>& opt) {
773 CONSTEXPR
bool operator>(
const Optional<T>& opt, nullopt_t) {
774 return opt.has_value();
778 CONSTEXPR
bool operator>(nullopt_t,
const Optional<T>& opt) {
783 CONSTEXPR
bool operator>=(
const Optional<T>& opt, nullopt_t) {
788 CONSTEXPR
bool operator>=(nullopt_t,
const Optional<T>& opt) {
792 template <
class T,
class U>
793 CONSTEXPR
bool operator==(
const Optional<T>& opt,
const U& value) {
794 return opt.has_value() ? *opt == value :
false;
797 template <
class T,
class U>
798 CONSTEXPR
bool operator==(
const U& value,
const Optional<T>& opt) {
799 return opt.has_value() ? value == *opt :
false;
802 template <
class T,
class U>
803 CONSTEXPR
bool operator!=(
const Optional<T>& opt,
const U& value) {
804 return opt.has_value() ? *opt != value :
true;
807 template <
class T,
class U>
808 CONSTEXPR
bool operator!=(
const U& value,
const Optional<T>& opt) {
809 return opt.has_value() ? value != *opt :
true;
812 template <
class T,
class U>
813 CONSTEXPR
bool operator<(
const Optional<T>& opt,
const U& value) {
814 return opt.has_value() ? *opt < value :
true;
817 template <
class T,
class U>
818 CONSTEXPR
bool operator<(
const U& value,
const Optional<T>& opt) {
819 return opt.has_value() ? value < *opt :
false;
822 template <
class T,
class U>
823 CONSTEXPR
bool operator<=(
const Optional<T>& opt,
const U& value) {
824 return opt.has_value() ? *opt <= value :
true;
827 template <
class T,
class U>
828 CONSTEXPR
bool operator<=(
const U& value,
const Optional<T>& opt) {
829 return opt.has_value() ? value <= *opt :
false;
832 template <
class T,
class U>
833 CONSTEXPR
bool operator>(
const Optional<T>& opt,
const U& value) {
834 return opt.has_value() ? *opt > value :
false;
837 template <
class T,
class U>
838 CONSTEXPR
bool operator>(
const U& value,
const Optional<T>& opt) {
839 return opt.has_value() ? value > *opt :
true;
842 template <
class T,
class U>
843 CONSTEXPR
bool operator>=(
const Optional<T>& opt,
const U& value) {
844 return opt.has_value() ? *opt >= value :
false;
847 template <
class T,
class U>
848 CONSTEXPR
bool operator>=(
const U& value,
const Optional<T>& opt) {
849 return opt.has_value() ? value >= *opt :
true;
852 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
853 template <
class T,
class... Args>
854 CONSTEXPR Optional<T> make_optional(Args&&... args) {
855 return Optional<T>(in_place, std::forward<Args>(args)...);
858 template <
class T,
class U,
class... Args>
859 CONSTEXPR Optional<T> make_optional(std::initializer_list<U> il,
861 return Optional<T>(in_place, il, std::forward<Args>(args)...);
870 void swap(Optional<T>& lhs, Optional<T>& rhs) {
876 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
879 struct hash<agora::Optional<T> > {
881 return opt == agora::nullopt ? 0 : std::hash<T>()(*opt);