20 #include <platform/macros.h> 24 #include <initializer_list> 25 #include <type_traits> 81 virtual const char* what()
const noexcept;
108 constexpr
nullopt_t nullopt(nullopt_t::init);
110 namespace internal_optional {
113 template <
typename T>
114 constexpr T&& forward(
typename std::remove_reference<T>::type&
116 return static_cast<T&&
>(t);
123 template <typename T, bool = std::is_trivially_destructible<T>::value>
134 void destruct() noexcept {
144 template <
typename... Args>
146 : engaged_(
true), data_(internal_optional::forward<Args>(args)...) {}
148 ~optional_data_dtor_base() { destruct(); }
152 template <
typename T>
162 void destruct() noexcept { engaged_ =
false; }
167 template <
typename... Args>
169 : engaged_(
true), data_(internal_optional::forward<Args>(args)...) {}
171 ~optional_data_dtor_base() =
default;
174 template <
typename T>
180 T* pointer() {
return &this->data_; }
182 constexpr
const T* pointer()
const {
return &this->data_; }
184 template <
typename... Args>
185 void construct(Args&&... args) {
186 new (pointer()) T(std::forward<Args>(args)...);
187 this->engaged_ =
true;
190 template <
typename U>
192 if (this->engaged_) {
193 this->data_ = std::forward<U>(u);
195 construct(std::forward<U>(u));
203 construct(rhs.data_);
208 std::is_nothrow_move_constructible<T>::value) {
210 construct(std::move(rhs.data_));
224 std::is_nothrow_move_assignable<T>::value&&
225 std::is_nothrow_move_constructible<T>::value) {
227 assign(std::move(rhs.data_));
237 enum class copy_traits { copyable = 0, movable = 1, non_movable = 2 };
240 template <copy_traits>
274 template <copy_traits>
307 template <
typename T>
308 constexpr copy_traits get_ctor_copy_traits() {
309 return std::is_copy_constructible<T>::value
310 ? copy_traits::copyable
311 : std::is_move_constructible<T>::value ? copy_traits::movable
312 : copy_traits::non_movable;
315 template <
typename T>
316 constexpr copy_traits get_assign_copy_traits() {
317 return std::is_copy_assignable<T>::value &&
318 std::is_copy_constructible<T>::value
319 ? copy_traits::copyable
320 : std::is_move_assignable<T>::value &&
321 std::is_move_constructible<T>::value
322 ? copy_traits::movable
323 : copy_traits::non_movable;
327 template <
typename T,
typename U>
329 : std::integral_constant<
330 bool, std::is_constructible<T, optional<U>&>::value ||
331 std::is_constructible<T, optional<U>&&>::value ||
332 std::is_constructible<T, const optional<U>&>::value ||
333 std::is_constructible<T, const optional<U>&&>::value ||
334 std::is_convertible<optional<U>&, T>::value ||
335 std::is_convertible<optional<U>&&, T>::value ||
336 std::is_convertible<const optional<U>&, T>::value ||
337 std::is_convertible<const optional<U>&&, T>::value> {};
340 template <
typename T,
typename U>
342 : std::integral_constant<
343 bool, is_constructible_convertible_from_optional<T, U>::value ||
344 std::is_assignable<T&, optional<U>&>::value ||
345 std::is_assignable<T&, optional<U>&&>::value ||
346 std::is_assignable<T&, const optional<U>&>::value ||
347 std::is_assignable<T&, const optional<U>&&>::value> {};
351 template <
typename T>
354 internal_optional::get_ctor_copy_traits<T>()>,
356 internal_optional::get_assign_copy_traits<T>()> {
360 typedef T value_type;
380 template <
typename... Args>
382 : data_base(
in_place_t(), internal_optional::forward<Args>(args)...) {}
386 template <
typename U,
typename... Args,
387 typename =
typename std::enable_if<std::is_constructible<
388 T, std::initializer_list<U>&, Args&&...>::value>::type>
389 constexpr
explicit optional(
in_place_t, std::initializer_list<U> il,
391 : data_base(
in_place_t(), il, internal_optional::forward<Args>(args)...) {
396 typename std::enable_if<
397 std::is_constructible<T, U&&>::value &&
398 !std::is_same<in_place_t, typename std::decay<U>::type>::value &&
399 !std::is_same<optional<T>,
typename std::decay<U>::type>::value &&
400 std::is_convertible<U&&, T>::value,
402 constexpr optional(U&& v)
403 : data_base(
in_place_t(), internal_optional::forward<U>(v)) {}
407 typename std::enable_if<
408 std::is_constructible<T, U&&>::value &&
409 !std::is_same<in_place_t, typename std::decay<U>::type>::value &&
410 !std::is_same<optional<T>,
typename std::decay<U>::type>::value &&
411 !std::is_convertible<U&&, T>::value,
413 explicit constexpr optional(U&& v)
414 : data_base(
in_place_t(), internal_optional::forward<U>(v)) {}
419 typename std::enable_if<
420 std::is_constructible<T, const U&>::value &&
423 std::is_convertible<const U&, T>::value,
427 this->construct(*rhs);
434 typename std::enable_if<
435 std::is_constructible<T, const U&>::value &&
438 !std::is_convertible<const U&, T>::value,
442 this->construct(*rhs);
449 typename std::enable_if<
450 std::is_constructible<T, U&&>::value &&
453 std::is_convertible<U&&, T>::value,
457 this->construct(std::move(*rhs));
464 typename std::enable_if<
465 std::is_constructible<T, U&&>::value &&
468 !std::is_convertible<U&&, T>::value,
472 this->construct(std::move(*rhs));
477 ~optional() =
default;
482 optional& operator=(
nullopt_t) noexcept {
488 optional& operator=(
const optional& src) =
default;
491 optional& operator=(optional&& src) =
default;
496 typename =
typename std::enable_if<
497 !std::is_same<optional<T>,
typename std::decay<U>::type>::value &&
498 (!std::is_scalar<T>::value ||
499 !std::is_same<T, typename std::decay<U>::type>::value) &&
500 std::is_constructible<T, U>::value &&
501 std::is_assignable<T&, U>::value>::type>
502 optional&
operator=(U&& v) {
503 this->assign(std::forward<U>(v));
507 template <
typename U,
508 typename =
typename std::enable_if<
509 std::is_constructible<T, const U&>::value &&
510 std::is_assignable<T&, const U&>::value &&
512 is_constructible_convertible_assignable_from_optional<
523 template <
typename U,
524 typename =
typename std::enable_if<
525 std::is_constructible<T, U>::value &&
526 std::is_assignable<T&, U>::value &&
528 is_constructible_convertible_assignable_from_optional<
532 this->assign(std::move(*rhs));
541 void reset() noexcept { this->destruct(); }
553 template <
typename... Args,
554 typename =
typename std::enable_if<
555 std::is_constructible<T, Args&&...>::value>::type>
556 void emplace(Args&&... args) {
558 this->construct(std::forward<Args>(args)...);
562 template <
class U,
class... Args,
563 typename =
typename std::enable_if<std::is_constructible<
564 T, std::initializer_list<U>&, Args&&...>::value>::type>
565 void emplace(std::initializer_list<U> il, Args&&... args) {
567 this->construct(il, std::forward<Args>(args)...);
572 void swap(optional& rhs) noexcept(
573 std::is_nothrow_move_constructible<T>::value&&
574 std::is_trivial<T>::value) {
580 rhs.construct(std::move(**
this));
585 this->construct(std::move(*rhs));
597 constexpr
const T* operator->()
const {
return this->pointer(); }
599 assert(this->engaged_);
600 return this->pointer();
602 constexpr
const T& operator*()
const & {
return reference(); }
604 assert(this->engaged_);
607 constexpr
const T&& operator*()
const && {
return std::move(reference()); }
609 assert(this->engaged_);
610 return std::move(reference());
622 constexpr
explicit operator bool()
const noexcept {
return this->engaged_; }
625 constexpr
bool has_value()
const noexcept {
return this->engaged_; }
630 const T& value()
const & {
643 return std::move(reference());
645 const T&& value()
const && {
648 return std::move(reference());
654 constexpr T value_or(U&& v)
const & {
655 return static_cast<bool>(*this) ? **this
656 :
static_cast<T
>(std::forward<U>(v));
659 T value_or(U&& v) && {
660 return static_cast<bool>(*this) ? std::move(**
this)
661 :
static_cast<T
>(std::forward<U>(v));
666 constexpr
const T& reference()
const {
return *this->pointer(); }
667 T& reference() {
return *(this->pointer()); }
672 !std::is_same<
nullopt_t,
typename std::remove_cv<T>::type>::value,
673 "optional<nullopt_t> is not allowed.");
675 !std::is_same<
in_place_t,
typename std::remove_cv<T>::type>::value,
676 "optional<in_place_t> is not allowed.");
677 static_assert(!std::is_reference<T>::value,
678 "optional<reference> is not allowed.");
687 template <
typename T,
688 typename std::enable_if<std::is_move_constructible<T>::value,
701 template <
typename T>
706 template <
typename T,
typename... Args>
707 constexpr
optional<T> make_optional(Args&&... args) {
711 template <
typename T,
typename U,
typename... Args>
712 constexpr
optional<T> make_optional(std::initializer_list<U> il,
715 internal_optional::forward<Args>(args)...);
731 return static_cast<bool>(x) != static_cast<bool>(y)
733 :
static_cast<bool>(x) ==
false ?
true : *x == *y;
739 return static_cast<bool>(x) != static_cast<bool>(y)
741 :
static_cast<bool>(x) ==
false ?
false : *x != *y;
745 constexpr
bool operator<(const optional<T>& x,
const optional<T>& y) {
746 return !y ? false : !x ? true : *x < *y;
751 return !x ? false : !y ? true : *x > *y;
755 constexpr
bool operator<=(const optional<T>& x,
const optional<T>& y) {
756 return !x ? true : !y ? false : *x <= *y;
761 return !y ? true : !x ? false : *x >= *y;
776 return static_cast<bool>(x);
780 return static_cast<bool>(x);
783 constexpr
bool operator<(const optional<T>& x ATTRIBUTE_UNUSED,
nullopt_t) noexcept {
787 constexpr
bool operator<(nullopt_t, const optional<T>& x) noexcept {
788 return static_cast<bool>(x);
791 constexpr
bool operator<=(const optional<T>& x,
nullopt_t) noexcept {
795 constexpr
bool operator<=(nullopt_t, const optional<T>& x ATTRIBUTE_UNUSED) noexcept {
800 return static_cast<bool>(x);
818 constexpr
bool operator==(
const optional<T>& x,
const T& v) {
819 return static_cast<bool>(x) ? *x == v :
false;
822 constexpr
bool operator==(
const T& v,
const optional<T>& x) {
823 return static_cast<bool>(x) ? v == *x :
false;
826 constexpr
bool operator!=(
const optional<T>& x,
const T& v) {
827 return static_cast<bool>(x) ? *x != v :
true;
830 constexpr
bool operator!=(
const T& v,
const optional<T>& x) {
831 return static_cast<bool>(x) ? v != *x :
true;
834 constexpr
bool operator<(const optional<T>& x,
const T& v) {
835 return static_cast<bool>(x) ? *x < v :
true;
838 constexpr
bool operator<(const T& v, const optional<T>& x) {
839 return static_cast<bool>(x) ? v < *x :
false;
842 constexpr
bool operator<=(const optional<T>& x,
const T& v) {
843 return static_cast<bool>(x) ? *x <= v :
true;
846 constexpr
bool operator<=(const T& v, const optional<T>& x) {
847 return static_cast<bool>(x) ? v <= *x :
false;
850 constexpr
bool operator>(
const optional<T>& x,
const T& v) {
851 return static_cast<bool>(x) ? *x > v :
false;
854 constexpr
bool operator>(
const T& v,
const optional<T>& x) {
855 return static_cast<bool>(x) ? v > *x :
true;
858 constexpr
bool operator>=(
const optional<T>& x,
const T& v) {
859 return static_cast<bool>(x) ? *x >= v :
false;
862 constexpr
bool operator>=(
const T& v,
const optional<T>& x) {
863 return static_cast<bool>(x) ? v >= *x :
true;
873 size_t operator()(const ::momemta::gtl::optional<T>& opt)
const {
875 return hash<T>()(*opt);
877 return static_cast<size_t>(0x297814aaad196e6dULL);