Files
BayesNet/html/libtorch/include/c10/util/Optional.h.gcov.html

140 KiB

<html lang="en"> <head> </head>
LCOV - code coverage report
Current view: top level - libtorch/include/c10/util - Optional.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 89.0 % 91 81
Test Date: 2024-04-30 13:17:26 Functions: 76.4 % 157 120

            Line data    Source code
       1              : // Copyright (C) 2011 - 2012 Andrzej Krzemienski.
       2              : //
       3              : // Use, modification, and distribution is subject to the Boost Software
       4              : // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
       5              : // http://www.boost.org/LICENSE_1_0.txt)
       6              : //
       7              : // The idea and interface is based on Boost.Optional library
       8              : // authored by Fernando Luis Cacciola Carballal
       9              : //
      10              : // From https://github.com/akrzemi1/Optional
      11              : //
      12              : // C10
      13              : // - Move file to `c10` namespace.
      14              : // - Remove macro use in line 478 because the nvcc device compiler cannot handle
      15              : // it.
      16              : // - Revise constructor logic so that it is 1) consistent with c++ 17 standard
      17              : // documented here in (8):
      18              : // https://en.cppreference.com/w/cpp/utility/optional/optional, and 2) able to
      19              : // support initialization of optionals from convertible type U.
      20              : // - Remove the constructors for `optional(const T&)` and `optional(T&&)`, as
      21              : // they can be handled by the template<U=T> case with the default template
      22              : // argument.
      23              : // - Move `constexpr struct in_place_t {} in_place{}` to `c10/util/in_place.h`
      24              : // so that it can also be used in `c10/util/variant.h`.
      25              : // - Remove special cases for pre-c++14 compilers to make code simpler.
      26              : 
      27              : #ifndef C10_UTIL_OPTIONAL_H_
      28              : #define C10_UTIL_OPTIONAL_H_
      29              : 
      30              : #include <c10/macros/Macros.h>
      31              : #include <c10/util/ArrayRef.h>
      32              : #include <c10/util/in_place.h>
      33              : 
      34              : #include <cassert>
      35              : #include <functional>
      36              : #include <initializer_list>
      37              : #include <stdexcept>
      38              : #include <string>
      39              : #include <type_traits>
      40              : #include <utility>
      41              : 
      42              : #include <c10/util/C++17.h>
      43              : #include <c10/util/Metaprogramming.h>
      44              : 
      45              : C10_CLANG_DIAGNOSTIC_PUSH()
      46              : #if C10_CLANG_HAS_WARNING("-Wstring-conversion")
      47              : C10_CLANG_DIAGNOSTIC_IGNORE("-Wstring-conversion")
      48              : #endif
      49              : #if C10_CLANG_HAS_WARNING("-Wshorten-64-to-32")
      50              : C10_CLANG_DIAGNOSTIC_IGNORE("-Wshorten-64-to-32")
      51              : #endif
      52              : #if C10_CLANG_HAS_WARNING("-Wimplicit-float-conversion")
      53              : C10_CLANG_DIAGNOSTIC_IGNORE("-Wimplicit-float-conversion")
      54              : #endif
      55              : #if C10_CLANG_HAS_WARNING("-Wimplicit-int-conversion")
      56              : C10_CLANG_DIAGNOSTIC_IGNORE("-Wimplicit-int-conversion")
      57              : #endif
      58              : 
      59              : #if defined(_MSC_VER) && !defined(__clang__)
      60              : #pragma warning(push)
      61              : #pragma warning(disable : 4624) // destructor was implicitly defined as deleted
      62              : #endif
      63              : 
      64              : #define TR2_OPTIONAL_REQUIRES(...) \
      65              :   typename std::enable_if<__VA_ARGS__::value, bool>::type = false
      66              : 
      67              : namespace c10 {
      68              : 
      69              : // 20.5.4, optional for object types
      70              : template <class T>
      71              : class optional;
      72              : 
      73              : // 20.5.5, optional for lvalue reference types
      74              : template <class T>
      75              : class optional<T&>;
      76              : 
      77              : // workaround: std utility functions aren't constexpr yet
      78              : template <class T>
      79    199233304 : inline constexpr T&& constexpr_forward(
      80              :     typename std::remove_reference<T>::type& t) noexcept {
      81    199233304 :   return static_cast<T&&>(t);
      82              : }
      83              : 
      84              : template <class T>
      85              : inline constexpr T&& constexpr_forward(
      86              :     typename std::remove_reference<T>::type&& t) noexcept {
      87              :   static_assert(!std::is_lvalue_reference<T>::value, "!!");
      88              :   return static_cast<T&&>(t);
      89              : }
      90              : 
      91              : template <class T>
      92    196750336 : inline constexpr typename std::remove_reference<T>::type&& constexpr_move(
      93              :     T&& t) noexcept {
      94    196750336 :   return static_cast<typename std::remove_reference<T>::type&&>(t);
      95              : }
      96              : 
      97              : #if defined NDEBUG
      98              : #define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR)
      99              : #else
     100              : #define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) \
     101              :   ((CHECK) ? (EXPR) : ([] { assert(!#CHECK); }(), (EXPR)))
     102              : #endif
     103              : 
     104              : #if defined(__CUDA_ARCH__)
     105              : #define TR2_OPTIONAL_HOST_CONSTEXPR
     106              : #else
     107              : #define TR2_OPTIONAL_HOST_CONSTEXPR constexpr
     108              : #endif
     109              : 
     110              : // Sphinx chokes on static_addressof, so exclude it from Doxygen
     111              : // generation.  See https://github.com/sphinx-doc/sphinx/issues/7944
     112              : // \cond
     113              : 
     114              : namespace detail_ {
     115              : 
     116              : // VS doesn't handle constexpr well, so we need to skip these stuff.
     117              : #if (defined _MSC_VER)
     118              : template <typename T>
     119              : T* static_addressof(T& ref) {
     120              :   return std::addressof(ref);
     121              : }
     122              : #else
     123              : // static_addressof: a constexpr version of addressof
     124              : template <typename T>
     125              : struct has_overloaded_addressof {
     126              :   template <class X>
     127              :   constexpr static bool has_overload(...) {
     128              :     return false;
     129              :   }
     130              : 
     131              :   template <class X, size_t S = sizeof(std::declval<X&>().operator&())>
     132              :   constexpr static bool has_overload(bool) {
     133              :     return true;
     134              :   }
     135              : 
     136              :   constexpr static bool value = has_overload<T>(true);
     137              : };
     138              : 
     139              : template <typename T, TR2_OPTIONAL_REQUIRES(!has_overloaded_addressof<T>)>
     140              : constexpr T* static_addressof(T& ref) {
     141              :   return &ref;
     142              : }
     143              : 
     144              : template <typename T, TR2_OPTIONAL_REQUIRES(has_overloaded_addressof<T>)>
     145              : T* static_addressof(T& ref) {
     146              :   return std::addressof(ref);
     147              : }
     148              : #endif
     149              : 
     150              : // the call to convert<A>(b) has return type A and converts b to type A iff b
     151              : // decltype(b) is implicitly convertible to A
     152              : template <class U>
     153            0 : constexpr U convert(U v) {
     154            0 :   return v;
     155              : }
     156              : 
     157              : } // namespace detail_
     158              : 
     159              : // \endcond
     160              : 
     161              : constexpr struct trivial_init_t {
     162              : } trivial_init{};
     163              : 
     164              : // 20.5.7, Disengaged state indicator
     165              : struct nullopt_t {
     166              :   constexpr explicit nullopt_t(int) {}
     167              : };
     168              : constexpr nullopt_t nullopt{0};
     169              : 
     170              : // 20.5.8, class bad_optional_access
     171              : class bad_optional_access : public std::logic_error {
     172              :  public:
     173              :   explicit bad_optional_access(const std::string& what_arg)
     174              :       : logic_error{what_arg} {}
     175            0 :   explicit bad_optional_access(const char* what_arg) : logic_error{what_arg} {}
     176              : };
     177              : 
     178              : template <class T>
     179              : union storage_t {
     180              :   unsigned char dummy_{};
     181              :   T value_;
     182              : 
     183              : #if __cplusplus >= 202002L
     184              :   constexpr
     185              : #endif
     186    216200968 :       storage_t(trivial_init_t) noexcept {
     187    216200968 :     new (&dummy_) unsigned char;
     188    216200968 :   }
     189              : 
     190              :   template <class... Args>
     191    105308712 :   constexpr storage_t(Args&&... args)
     192    105308712 :       : value_(constexpr_forward<Args>(args)...) {}
     193              : 
     194    321509680 :   ~storage_t() {}
     195              : };
     196              : 
     197              : template <class T>
     198              : union constexpr_storage_t {
     199              :   unsigned char dummy_;
     200              :   T value_;
     201              : 
     202              : #if __cplusplus >= 202002L
     203              :   // C++20 lifted the requirement to initialize a union member in order to be
     204              :   // constexpr.
     205              :   constexpr constexpr_storage_t(trivial_init_t) noexcept {
     206              :     new (&dummy_) unsigned char;
     207              :   }
     208              : #else
     209      2945770 :   constexpr constexpr_storage_t(trivial_init_t) noexcept : dummy_() {}
     210              : #endif
     211              : 
     212              :   template <class... Args>
     213     92688986 :   constexpr constexpr_storage_t(Args&&... args)
     214     92688986 :       : value_(constexpr_forward<Args>(args)...) {}
     215              : 
     216              :   ~constexpr_storage_t() = default;
     217              : };
     218              : 
     219              : template <class T>
     220              : struct optional_base {
     221              :   bool init_;
     222              :   storage_t<T> storage_;
     223              : 
     224    110924592 :   constexpr optional_base() noexcept : init_(false), storage_(trivial_init){};
     225              : 
     226              :   explicit constexpr optional_base(const optional_base<T>& v)
     227              :       : init_(v.init_), storage_(trivial_init) {
     228              :     if (init_) {
     229              :       ::new (dataptr()) T(v.storage_.value_);
     230              :     }
     231              :   }
     232              : 
     233        31316 :   explicit constexpr optional_base(const T& v) : init_(true), storage_(v) {}
     234              : 
     235    105276376 :   explicit constexpr optional_base(optional_base<T>&& v) noexcept(
     236              :       std::is_nothrow_move_constructible<T>::value)
     237    105276376 :       : init_(v.init_), storage_(trivial_init) {
     238    105276376 :     if (init_) {
     239    105276376 :       ::new (dataptr()) T(std::move(v.storage_.value_));
     240              :     }
     241    105276376 :   }
     242              : 
     243    105277396 :   explicit constexpr optional_base(T&& v)
     244    105277396 :       : init_(true), storage_(constexpr_move(v)) {}
     245              : 
     246              :   template <class... Args>
     247              :   explicit optional_base(in_place_t, Args&&... args)
     248              :       : init_(true), storage_(constexpr_forward<Args>(args)...) {}
     249              : 
     250              :   template <
     251              :       class U,
     252              :       class... Args,
     253              :       TR2_OPTIONAL_REQUIRES(std::is_constructible<T, std::initializer_list<U>>)>
     254              :   explicit optional_base(
     255              :       in_place_t,
     256              :       std::initializer_list<U> il,
     257              :       Args&&... args)
     258              :       : init_(true), storage_(il, std::forward<Args>(args)...) {}
     259              : 
     260              :   optional_base& operator=(const optional_base& rhs) {
     261              :     if (init_ && !rhs.init_) {
     262              :       clear();
     263              :     } else if (!init_ && rhs.init_) {
     264              :       init_ = true;
     265              :       ::new (dataptr()) T(rhs.storage_.value_);
     266              :     } else if (init_ && rhs.init_) {
     267              :       storage_.value_ = rhs.storage_.value_;
     268              :     }
     269              :     return *this;
     270              :   }
     271              : 
     272              :   optional_base& operator=(optional_base&& rhs) noexcept(
     273              :       std::is_nothrow_move_assignable<T>::value&&
     274              :           std::is_nothrow_move_constructible<T>::value) {
     275              :     if (init_ && !rhs.init_) {
     276              :       clear();
     277              :     } else if (!init_ && rhs.init_) {
     278              :       init_ = true;
     279              :       ::new (dataptr()) T(std::move(rhs.storage_.value_));
     280              :     } else if (init_ && rhs.init_) {
     281              :       storage_.value_ = std::move(rhs.storage_.value_);
     282              :     }
     283              :     return *this;
     284              :   }
     285              : 
     286    321509680 :   ~optional_base() {
     287    321509680 :     if (init_)
     288    210585088 :       storage_.value_.T::~T();
     289    321509680 :   }
     290              : 
     291    321479384 :   constexpr bool initialized() const noexcept {
     292    321479384 :     return init_;
     293              :   }
     294              : 
     295              :   void setInitialized(bool init) noexcept {
     296              :     init_ = init;
     297              :   }
     298              : 
     299              :  private:
     300    105276376 :   typename std::remove_const<T>::type* dataptr() {
     301    105276376 :     return std::addressof(storage_.value_);
     302              :   }
     303              : 
     304              :   constexpr const T* dataptr() const {
     305              :     return detail_::static_addressof(storage_.value_);
     306              :   }
     307              : 
     308              :   void clear() noexcept {
     309              :     if (init_) {
     310              :       dataptr()->~T();
     311              :     }
     312              :     init_ = false;
     313              :   }
     314              : };
     315              : 
     316              : template <class T>
     317              : struct constexpr_optional_base {
     318              :   bool init_;
     319              :   constexpr_storage_t<T> storage_;
     320              : 
     321              :   constexpr constexpr_optional_base() noexcept
     322              :       : init_(false), storage_(trivial_init){};
     323              : 
     324              :   explicit constexpr constexpr_optional_base(
     325              :       const constexpr_optional_base<T>& v)
     326              :       : init_(v.init_), storage_(trivial_init) {
     327              :     if (init_) {
     328              :       ::new (dataptr()) T(v.storage_.value_);
     329              :     }
     330              :   }
     331              : 
     332              :   explicit constexpr constexpr_optional_base(
     333              :       constexpr_optional_base<T>&&
     334              :           v) noexcept(std::is_nothrow_move_constructible<T>::value)
     335              :       : init_(v.init_), storage_(trivial_init) {
     336              :     if (init_) {
     337              :       ::new (dataptr()) T(std::move(v.storage_.value_));
     338              :     }
     339              :   }
     340              : 
     341              :   explicit constexpr constexpr_optional_base(const T& v)
     342              :       : init_(true), storage_(v) {}
     343              : 
     344              :   explicit constexpr constexpr_optional_base(T&& v)
     345              :       : init_(true), storage_(constexpr_move(v)) {}
     346              : 
     347              :   template <class... Args>
     348              :   explicit constexpr constexpr_optional_base(in_place_t, Args&&... args)
     349              :       : init_(true), storage_(constexpr_forward<Args>(args)...) {}
     350              : 
     351              :   template <
     352              :       class U,
     353              :       class... Args,
     354              :       TR2_OPTIONAL_REQUIRES(std::is_constructible<T, std::initializer_list<U>>)>
     355              :   constexpr explicit constexpr_optional_base(
     356              :       in_place_t,
     357              :       std::initializer_list<U> il,
     358              :       Args&&... args)
     359              :       : init_(true), storage_(il, std::forward<Args>(args)...) {}
     360              : 
     361              :   ~constexpr_optional_base() = default;
     362              : 
     363              :   constexpr_optional_base& operator=(const constexpr_optional_base& rhs) {
     364              :     if (init_ && !rhs.init_) {
     365              :       clear();
     366              :     } else if (!init_ && rhs.init_) {
     367              :       init_ = true;
     368              :       ::new (dataptr()) T(rhs.storage_.value_);
     369              :     } else if (init_ && rhs.init_) {
     370              :       storage_.value_ = rhs.storage_.value_;
     371              :     }
     372              :     return *this;
     373              :   }
     374              : 
     375              :   constexpr_optional_base& operator=(constexpr_optional_base&& rhs) noexcept(
     376              :       std::is_nothrow_move_assignable<T>::value&&
     377              :           std::is_nothrow_move_constructible<T>::value) {
     378              :     if (init_ && !rhs.init_) {
     379              :       clear();
     380              :     } else if (!init_ && rhs.init_) {
     381              :       init_ = true;
     382              :       ::new (dataptr()) T(std::move(rhs.storage_.value_));
     383              :     } else if (init_ && rhs.init_) {
     384              :       storage_.value_ = std::move(rhs.storage_.value_);
     385              :     }
     386              :     return *this;
     387              :   }
     388              : 
     389              :   constexpr bool initialized() const noexcept {
     390              :     return init_;
     391              :   }
     392              :   void setInitialized(bool init) noexcept {
     393              :     init_ = init;
     394              :   }
     395              : 
     396              :  private:
     397              :   typename std::remove_const<T>::type* dataptr() {
     398              :     return std::addressof(storage_.value_);
     399              :   }
     400              : 
     401              :   constexpr const T* dataptr() const {
     402              :     return detail_::static_addressof(storage_.value_);
     403              :   }
     404              : 
     405              :   void clear() noexcept {
     406              :     init_ = false;
     407              :   }
     408              : };
     409              : 
     410              : // HACK: Optimization for trivially copyable types. The mainline
     411              : // implementation fails to have trivial copy/move operations in these
     412              : // cases, and we care about them, so just implement that directly.
     413              : template <class T>
     414              : struct trivially_copyable_optimization_optional_base {
     415              :   bool init_;
     416              :   constexpr_storage_t<T> storage_;
     417              : 
     418      2945770 :   constexpr trivially_copyable_optimization_optional_base() noexcept
     419      2945770 :       : init_(false), storage_(trivial_init) {}
     420              : 
     421       814728 :   explicit constexpr trivially_copyable_optimization_optional_base(const T& v)
     422       814728 :       : init_(true), storage_(v) {}
     423              : 
     424     91472940 :   explicit constexpr trivially_copyable_optimization_optional_base(T&& v)
     425     91472940 :       : init_(true), storage_(constexpr_move(v)) {}
     426              : 
     427              :   template <class... Args>
     428       401318 :   explicit constexpr trivially_copyable_optimization_optional_base(
     429              :       in_place_t,
     430              :       Args&&... args)
     431       401318 :       : init_(true), storage_(constexpr_forward<Args>(args)...) {}
     432              : 
     433              :   template <
     434              :       class U,
     435              :       class... Args,
     436              :       TR2_OPTIONAL_REQUIRES(std::is_constructible<T, std::initializer_list<U>>)>
     437              :   constexpr explicit trivially_copyable_optimization_optional_base(
     438              :       in_place_t,
     439              :       std::initializer_list<U> il,
     440              :       Args&&... args)
     441              :       : init_(true), storage_(il, std::forward<Args>(args)...) {}
     442              : 
     443              :   ~trivially_copyable_optimization_optional_base() = default;
     444              : 
     445    185760028 :   constexpr bool initialized() const noexcept {
     446    185760028 :     return init_;
     447              :   }
     448              :   void setInitialized(bool init) noexcept {
     449              :     init_ = init;
     450              :   }
     451              : };
     452              : 
     453              : // HACK: Optimization for ArrayRef<T>. We take advantage of an unused
     454              : // bit pattern in ArrayRef (inspired by Arthur O'Dwyer's
     455              : // tombstone_traits -- see https://youtu.be/MWBfmmg8-Yo?t=2466) to
     456              : // keep the size of c10::optional::ArrayRef<T> down to 16 bytes, which
     457              : // allows it to be passed to functions in registers instead of getting
     458              : // passed in memory per item 5c of the classification algorithm in
     459              : // section 3.2.3 of the System V ABI document
     460              : // (https://www.uclibc.org/docs/psABI-x86_64.pdf).
     461              : template <class ArrayRefT>
     462              : class arrayref_optional_base {
     463              :  public:
     464              :   union storage {
     465              :     struct raw {
     466              :       // ArrayRef has the invariant that if Data is nullptr then
     467              :       // Length must be zero, so this is an unused bit pattern.
     468              :       const void* p = nullptr;
     469              :       size_t sz = 1;
     470              :     } uninitialized_{};
     471              :     ArrayRefT value_;
     472              : 
     473        16480 :     constexpr storage() noexcept : uninitialized_() {
     474        16480 :       setUninitialized();
     475        16480 :     }
     476              : 
     477        16480 :     constexpr void setUninitialized() noexcept {
     478        16480 :       uninitialized_.p = nullptr;
     479        16480 :       uninitialized_.sz = 1;
     480        16480 :     }
     481              : 
     482              :     explicit constexpr storage(ArrayRefT& v) : value_(v) {}
     483              : 
     484              :     template <typename T>
     485              :     explicit constexpr storage(const std::initializer_list<T>& v) : value_(v) {}
     486              : 
     487              :     template <class... Args>
     488        14194 :     explicit constexpr storage(Args&&... args)
     489        14194 :         : value_(constexpr_forward<Args>(args)...) {}
     490              :   };
     491              : 
     492              :   storage storage_;
     493              : 
     494        16480 :   constexpr arrayref_optional_base() noexcept = default;
     495              : 
     496        14194 :   explicit constexpr arrayref_optional_base(const ArrayRefT& v) : storage_(v) {}
     497              : 
     498              :   template <class... Args>
     499              :   explicit constexpr arrayref_optional_base(in_place_t, Args&&... args)
     500              :       : storage_(constexpr_forward<Args>(args)...) {}
     501              : 
     502              :   template <typename T>
     503              :   explicit constexpr arrayref_optional_base(
     504              :       in_place_t,
     505              :       const std::initializer_list<T>& v)
     506              :       : storage_(v) {}
     507              : 
     508              :   constexpr bool initialized() const noexcept {
     509              :     return storage_.uninitialized_.p != nullptr ||
     510              :         storage_.uninitialized_.sz == 0;
     511              :   }
     512              : 
     513              :   void setInitialized(bool init) noexcept {
     514              :     if (!init) {
     515              :       storage_.setUninitialized();
     516              :     } else {
     517              :       assert(initialized());
     518              :     }
     519              :   }
     520              : };
     521              : 
     522              : namespace detail_ {
     523              : template <typename T>
     524              : struct is_arrayref : std::false_type {};
     525              : 
     526              : template <typename T>
     527              : struct is_arrayref<c10::ArrayRef<T>> : std::true_type {};
     528              : } // namespace detail_
     529              : 
     530              : template <class T>
     531              : using OptionalBase = std::conditional_t<
     532              :     detail_::is_arrayref<T>::value,
     533              :     arrayref_optional_base<T>,
     534              :     std::conditional_t<
     535              :         std::is_trivially_destructible<T>::value &&
     536              :             C10_IS_TRIVIALLY_COPYABLE(T) &&
     537              :             // Avoid using is_trivially_copy_{constructible,assignable}
     538              :             // because old GCC versions don't support them. Also,
     539              :             // is_trivially_copyable seems not to do what I expect, so check
     540              :             // trivially_copyable_optimization_optional_base directly.
     541              :             std::is_copy_constructible<
     542              :                 trivially_copyable_optimization_optional_base<T>>::value &&
     543              :             std::is_copy_assignable<
     544              :                 trivially_copyable_optimization_optional_base<T>>::value,
     545              :         trivially_copyable_optimization_optional_base<T>,
     546              :         std::conditional_t<
     547              :             std::is_trivially_destructible<T>::value, // if possible
     548              :             constexpr_optional_base<std::remove_const_t<T>>, // use base with
     549              :                                                              // trivial
     550              :                                                              // destructor
     551              :             optional_base<std::remove_const_t<T>>>>>;
     552              : 
     553              : template <class T>
     554              : class optional : private OptionalBase<T> {
     555              :   template <class U> // re-declaration for nvcc on Windows.
     556              :   using OptionalBase = std::conditional_t<
     557              :       detail_::is_arrayref<U>::value,
     558              :       arrayref_optional_base<U>,
     559              :       std::conditional_t<
     560              :           std::is_trivially_destructible<U>::value &&
     561              :               C10_IS_TRIVIALLY_COPYABLE(U) &&
     562              :               // Avoid using is_trivially_copy_{constructible,assignable}
     563              :               // because old GCC versions don't support them. Also,
     564              :               // is_trivially_copyable seems not to do what I expect, so
     565              :               // check trivially_copyable_optimization_optional_base
     566              :               // directly.
     567              :               std::is_copy_constructible<
     568              :                   trivially_copyable_optimization_optional_base<U>>::value &&
     569              :               std::is_copy_assignable<
     570              :                   trivially_copyable_optimization_optional_base<U>>::value,
     571              :           trivially_copyable_optimization_optional_base<U>,
     572              :           std::conditional_t<
     573              :               std::is_trivially_destructible<U>::value, // if possible
     574              :               constexpr_optional_base<std::remove_const_t<U>>, // use base
     575              :                                                                // with
     576              :                                                                // trivial
     577              :                                                                // destructor
     578              :               optional_base<std::remove_const_t<U>>>>>;
     579              : 
     580              :   static_assert(
     581              :       !std::is_same<typename std::decay<T>::type, nullopt_t>::value,
     582              :       "bad T");
     583              :   static_assert(
     584              :       !std::is_same<typename std::decay<T>::type, in_place_t>::value,
     585              :       "bad T");
     586              : 
     587    507239412 :   constexpr bool initialized() const noexcept {
     588    507239412 :     return OptionalBase<T>::initialized();
     589              :   }
     590       418776 :   typename std::remove_const<T>::type* dataptr() {
     591       418776 :     return std::addressof(OptionalBase<T>::storage_.value_);
     592              :   }
     593              :   constexpr const T* dataptr() const {
     594              :     return detail_::static_addressof(OptionalBase<T>::storage_.value_);
     595              :   }
     596              : 
     597            0 :   constexpr const T& contained_val() const& {
     598            0 :     return OptionalBase<T>::storage_.value_;
     599              :   }
     600              :   constexpr T&& contained_val() && {
     601              :     return std::move(OptionalBase<T>::storage_.value_);
     602              :   }
     603    197127776 :   constexpr T& contained_val() & {
     604    197127776 :     return OptionalBase<T>::storage_.value_;
     605              :   }
     606              : 
     607              :   void clear() noexcept {
     608              :     if (initialized())
     609              :       dataptr()->~T();
     610              :     OptionalBase<T>::setInitialized(false);
     611              :   }
     612              : 
     613              :   template <class... Args>
     614              :   void initialize(Args&&... args) noexcept(
     615              :       noexcept(T(std::forward<Args>(args)...))) {
     616              :     assert(!initialized());
     617              :     ::new (static_cast<void*>(dataptr())) T(std::forward<Args>(args)...);
     618              :     OptionalBase<T>::setInitialized(true);
     619              :   }
     620              : 
     621              :   template <class U, class... Args>
     622              :   void initialize(std::initializer_list<U> il, Args&&... args) noexcept(
     623              :       noexcept(T(il, std::forward<Args>(args)...))) {
     624              :     assert(!initialized());
     625              :     ::new (static_cast<void*>(dataptr())) T(il, std::forward<Args>(args)...);
     626              :     OptionalBase<T>::setInitialized(true);
     627              :   }
     628              : 
     629              :  public:
     630              :   typedef T value_type;
     631              : 
     632              :   // 20.5.5.1, constructors
     633        16480 :   constexpr optional() noexcept = default;
     634    113870362 :   constexpr optional(nullopt_t) noexcept : OptionalBase<T>(){};
     635              : 
     636              :   optional(const optional& rhs) = default;
     637    105276376 :   optional(optional&& rhs) = default;
     638              : 
     639              :   // see https://github.com/akrzemi1/Optional/issues/16
     640              :   // and https://en.cppreference.com/w/cpp/utility/optional/optional,
     641              :   // in constructor 8, the std::optional spec can allow initialization
     642              :   // of optionals from convertible type U
     643              :   //
     644              :   // 8 - implicit move construct from value
     645              :   template <
     646              :       typename U = T,
     647              :       TR2_OPTIONAL_REQUIRES(
     648              :           std::is_constructible<T, U&&>::value &&
     649              :           !std::is_same<typename std::decay<U>::type, in_place_t>::value &&
     650              :           !std::is_same<typename std::decay<U>::type, optional<T>>::value &&
     651              :           std::is_convertible<U&&, T>)>
     652    197610574 :   constexpr optional(U&& u) : OptionalBase<T>(std::forward<U>(u)) {}
     653              : 
     654              :   // 8 - explicit move construct from value
     655              :   template <
     656              :       typename U = T,
     657              :       TR2_OPTIONAL_REQUIRES(
     658              :           std::is_constructible<T, U&&>::value &&
     659              :           !std::is_same<typename std::decay<U>::type, in_place_t>::value &&
     660              :           !std::is_same<typename std::decay<U>::type, optional<T>>::value &&
     661              :           !std::is_convertible<U&&, T>)>
     662              :   explicit constexpr optional(U&& u) : OptionalBase<T>(std::forward<U>(u)) {}
     663              : 
     664              :   template <class... Args>
     665       401318 :   explicit constexpr optional(in_place_t, Args&&... args)
     666       401318 :       : OptionalBase<T>(in_place_t{}, constexpr_forward<Args>(args)...) {}
     667              : 
     668              :   template <
     669              :       class U,
     670              :       class... Args,
     671              :       TR2_OPTIONAL_REQUIRES(std::is_constructible<T, std::initializer_list<U>>)>
     672              :   constexpr explicit optional(
     673              :       in_place_t,
     674              :       std::initializer_list<U> il,
     675              :       Args&&... args)
     676              :       : OptionalBase<T>(in_place_t{}, il, constexpr_forward<Args>(args)...) {}
     677              : 
     678              :   // 20.5.4.2, Destructor
     679    321509680 :   ~optional() = default;
     680              : 
     681              :   // 20.5.4.3, assignment
     682              :   optional& operator=(nullopt_t) noexcept {
     683              :     clear();
     684              :     return *this;
     685              :   }
     686              : 
     687              :   optional& operator=(const optional& rhs) = default;
     688              : 
     689              :   optional& operator=(optional&& rhs) = default;
     690              : 
     691              :   template <class U = T>
     692              :   auto operator=(U&& v) -> typename std::enable_if<
     693              :       std::is_constructible<T, U>::value &&
     694              :           !std::is_same<typename std::decay<U>::type, optional<T>>::value &&
     695              :           (std::is_scalar<T>::value ||
     696              :            std::is_same<typename std::decay<U>::type, T>::value) &&
     697              :           std::is_assignable<T&, U>::value,
     698              :       optional&>::type {
     699              :     if (initialized()) {
     700              :       contained_val() = std::forward<U>(v);
     701              :     } else {
     702              :       initialize(std::forward<U>(v));
     703              :     }
     704              :     return *this;
     705              :   }
     706              : 
     707              :   template <class... Args>
     708              :   void emplace(Args&&... args) {
     709              :     clear();
     710              :     initialize(std::forward<Args>(args)...);
     711              :   }
     712              : 
     713              :   template <class U, class... Args>
     714              :   void emplace(std::initializer_list<U> il, Args&&... args) {
     715              :     clear();
     716              :     initialize<U, Args...>(il, std::forward<Args>(args)...);
     717              :   }
     718              : 
     719              :   // 20.5.4.4, Swap
     720              :   void swap(optional<T>& rhs) noexcept(
     721              :       std::is_nothrow_move_constructible<T>::value&& noexcept(
     722              :           std::swap(std::declval<T&>(), std::declval<T&>()))) {
     723              :     if (initialized() == true && rhs.initialized() == false) {
     724              :       rhs.initialize(std::move(**this));
     725              :       clear();
     726              :     } else if (initialized() == false && rhs.initialized() == true) {
     727              :       initialize(std::move(*rhs));
     728              :       rhs.clear();
     729              :     } else if (initialized() == true && rhs.initialized() == true) {
     730              :       using std::swap;
     731              :       swap(**this, *rhs);
     732              :     }
     733              :   }
     734              : 
     735              :   // 20.5.4.5, Observers
     736              : 
     737     92670626 :   explicit constexpr operator bool() const noexcept {
     738     92670626 :     return initialized();
     739              :   }
     740    217022234 :   constexpr bool has_value() const noexcept {
     741    217022234 :     return initialized();
     742              :   }
     743              : 
     744              :   TR2_OPTIONAL_HOST_CONSTEXPR T const* operator->() const {
     745              :     return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr());
     746              :   }
     747              : 
     748       418776 :   TR2_OPTIONAL_HOST_CONSTEXPR T* operator->() {
     749       418776 :     assert(initialized());
     750       418776 :     return dataptr();
     751              :   }
     752              : 
     753            0 :   TR2_OPTIONAL_HOST_CONSTEXPR T const& operator*() const& {
     754            0 :     return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val());
     755              :   }
     756              : 
     757    197126756 :   TR2_OPTIONAL_HOST_CONSTEXPR T& operator*() & {
     758    197126756 :     assert(initialized());
     759    197126756 :     return contained_val();
     760              :   }
     761              : 
     762              :   TR2_OPTIONAL_HOST_CONSTEXPR T&& operator*() && {
     763              :     assert(initialized());
     764              :     return constexpr_move(contained_val());
     765              :   }
     766              : 
     767              :   TR2_OPTIONAL_HOST_CONSTEXPR T const& value() const& {
     768              :     return initialized()
     769              :         ? contained_val()
     770              :         : (throw bad_optional_access("bad optional access"), contained_val());
     771              :   }
     772              : 
     773              :   TR2_OPTIONAL_HOST_CONSTEXPR T& value() & {
     774              :     return initialized()
     775              :         ? contained_val()
     776              :         : (throw bad_optional_access("bad optional access"), contained_val());
     777              :   }
     778              : 
     779         1020 :   TR2_OPTIONAL_HOST_CONSTEXPR T&& value() && {
     780         1020 :     if (!initialized())
     781            0 :       throw bad_optional_access("bad optional access");
     782         1020 :     return std::move(contained_val());
     783              :   }
     784              : 
     785              :   template <class V>
     786              :   constexpr T value_or(V&& v) const& {
     787              :     return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v));
     788              :   }
     789              : 
     790              :   template <class V>
     791              :   constexpr T value_or(V&& v) && {
     792              :     return *this
     793              :         ? constexpr_move(const_cast<optional<T>&>(*this).contained_val())
     794              :         : detail_::convert<T>(constexpr_forward<V>(v));
     795              :   }
     796              : 
     797              :   // 20.6.3.6, modifiers
     798              :   void reset() noexcept {
     799              :     clear();
     800              :   }
     801              : };
     802              : 
     803              : template <class T, class F>
     804            0 : constexpr T value_or_else(const optional<T>& v, F&& func) {
     805              :   static_assert(
     806              :       std::is_convertible<
     807              :           typename guts::infer_function_traits_t<F>::return_type,
     808              :           T>::value,
     809              :       "func parameters must be a callable that returns a type convertible to the value stored in the optional");
     810            0 :   return v.has_value() ? *v : detail_::convert<T>(std::forward<F>(func)());
     811              : }
     812              : 
     813              : template <class T, class F>
     814              : constexpr T value_or_else(optional<T>&& v, F&& func) {
     815              :   static_assert(
     816              :       std::is_convertible<
     817              :           typename guts::infer_function_traits_t<F>::return_type,
     818              :           T>::value,
     819              :       "func parameters must be a callable that returns a type convertible to the value stored in the optional");
     820              :   return v.has_value() ? constexpr_move(std::move(v).contained_val())
     821              :                        : detail_::convert<T>(std::forward<F>(func)());
     822              : }
     823              : 
     824              : // XXX: please refrain from using optional<T&>, since it is being against with
     825              : // the optional standard in c++ 17, see the debate and the details here:
     826              : // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3406#rationale.refs
     827              : // if you need it, consider using optional<std::reference_wrapper<T>> or *
     828              : // pointer
     829              : //
     830              : // we leave the implementation here in case we want to reconsider using it in
     831              : // the future if it becomes a definitely necessary case.
     832              : template <class T>
     833              : class optional<T&> {
     834              :   // add this assert to prevent user from using optional reference as indicated
     835              :   // above
     836              :   static_assert(
     837              :       sizeof(T) == 0,
     838              :       "optional references is ill-formed, \
     839              :     consider use optional of a std::reference_wrapper of type T to \
     840              :     hold a reference if you really need to");
     841              : 
     842              :   static_assert(!std::is_same<T, nullopt_t>::value, "bad T");
     843              :   static_assert(!std::is_same<T, in_place_t>::value, "bad T");
     844              :   T* ref;
     845              : 
     846              :  public:
     847              :   // 20.5.5.1, construction/destruction
     848              :   constexpr optional() noexcept : ref(nullptr) {}
     849              : 
     850              :   constexpr optional(nullopt_t) noexcept : ref(nullptr) {}
     851              : 
     852              :   template <typename U = T>
     853              :   constexpr optional(U& u) noexcept : ref(detail_::static_addressof(u)) {}
     854              : 
     855              :   template <typename U = T>
     856              :   optional(U&&) = delete;
     857              : 
     858              :   constexpr optional(const optional& rhs) noexcept : ref(rhs.ref) {}
     859              : 
     860              :   explicit constexpr optional(in_place_t, T& v) noexcept
     861              :       : ref(detail_::static_addressof(v)) {}
     862              : 
     863              :   explicit optional(in_place_t, T&&) = delete;
     864              : 
     865              :   ~optional() = default;
     866              : 
     867              :   // 20.5.5.2, mutation
     868              :   optional& operator=(nullopt_t) noexcept {
     869              :     ref = nullptr;
     870              :     return *this;
     871              :   }
     872              : 
     873              :   // optional& operator=(const optional& rhs) noexcept {
     874              :   // ref = rhs.ref;
     875              :   // return *this;
     876              :   // }
     877              : 
     878              :   // optional& operator=(optional&& rhs) noexcept {
     879              :   // ref = rhs.ref;
     880              :   // return *this;
     881              :   // }
     882              : 
     883              :   template <typename U>
     884              :   auto operator=(U&& rhs) noexcept -> typename std::enable_if<
     885              :       std::is_same<typename std::decay<U>::type, optional<T&>>::value,
     886              :       optional&>::type {
     887              :     ref = rhs.ref;
     888              :     return *this;
     889              :   }
     890              : 
     891              :   template <typename U>
     892              :   auto operator=(U&& rhs) noexcept -> typename std::enable_if<
     893              :       !std::is_same<typename std::decay<U>::type, optional<T&>>::value,
     894              :       optional&>::type = delete;
     895              : 
     896              :   void emplace(T& v) noexcept {
     897              :     ref = detail_::static_addressof(v);
     898              :   }
     899              : 
     900              :   void emplace(T&&) = delete;
     901              : 
     902              :   void swap(optional<T&>& rhs) noexcept {
     903              :     std::swap(ref, rhs.ref);
     904              :   }
     905              : 
     906              :   // 20.5.5.3, observers
     907              :   TR2_OPTIONAL_HOST_CONSTEXPR T* operator->() const {
     908              :     return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref);
     909              :   }
     910              : 
     911              :   TR2_OPTIONAL_HOST_CONSTEXPR T& operator*() const {
     912              :     return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref);
     913              :   }
     914              : 
     915              :   constexpr T& value() const {
     916              :     return ref ? *ref
     917              :                : (throw bad_optional_access("bad optional access"), *ref);
     918              :   }
     919              : 
     920              :   explicit constexpr operator bool() const noexcept {
     921              :     return ref != nullptr;
     922              :   }
     923              : 
     924              :   constexpr bool has_value() const noexcept {
     925              :     return ref != nullptr;
     926              :   }
     927              : 
     928              :   template <class V>
     929              :   constexpr typename std::decay<T>::type value_or(V&& v) const {
     930              :     return *this ? **this
     931              :                  : detail_::convert<typename std::decay<T>::type>(
     932              :                        constexpr_forward<V>(v));
     933              :   }
     934              : 
     935              :   // x.x.x.x, modifiers
     936              :   void reset() noexcept {
     937              :     ref = nullptr;
     938              :   }
     939              : };
     940              : 
     941              : template <class T>
     942              : class optional<T&&> {
     943              :   static_assert(sizeof(T) == 0, "optional rvalue references disallowed");
     944              : };
     945              : 
     946              : // 20.5.8, Relational operators
     947              : template <class T>
     948              : constexpr bool operator==(const optional<T>& x, const optional<T>& y) {
     949              :   return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y;
     950              : }
     951              : 
     952              : template <class T>
     953              : constexpr bool operator!=(const optional<T>& x, const optional<T>& y) {
     954              :   return !(x == y);
     955              : }
     956              : 
     957              : template <class T>
     958              : constexpr bool operator<(const optional<T>& x, const optional<T>& y) {
     959              :   return (!y) ? false : (!x) ? true : *x < *y;
     960              : }
     961              : 
     962              : template <class T>
     963              : constexpr bool operator>(const optional<T>& x, const optional<T>& y) {
     964              :   return (y < x);
     965              : }
     966              : 
     967              : template <class T>
     968              : constexpr bool operator<=(const optional<T>& x, const optional<T>& y) {
     969              :   return !(y < x);
     970              : }
     971              : 
     972              : template <class T>
     973              : constexpr bool operator>=(const optional<T>& x, const optional<T>& y) {
     974              :   return !(x < y);
     975              : }
     976              : 
     977              : // 20.5.9, Comparison with nullopt
     978              : template <class T>
     979       401402 : constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept {
     980       401402 :   return (!x);
     981              : }
     982              : 
     983              : template <class T>
     984              : constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept {
     985              :   return (!x);
     986              : }
     987              : 
     988              : template <class T>
     989              : constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept {
     990              :   return bool(x);
     991              : }
     992              : 
     993              : template <class T>
     994              : constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept {
     995              :   return bool(x);
     996              : }
     997              : 
     998              : template <class T>
     999              : constexpr bool operator<(const optional<T>&, nullopt_t) noexcept {
    1000              :   return false;
    1001              : }
    1002              : 
    1003              : template <class T>
    1004              : constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept {
    1005              :   return bool(x);
    1006              : }
    1007              : 
    1008              : template <class T>
    1009              : constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept {
    1010              :   return (!x);
    1011              : }
    1012              : 
    1013              : template <class T>
    1014              : constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept {
    1015              :   return true;
    1016              : }
    1017              : 
    1018              : template <class T>
    1019              : constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept {
    1020              :   return bool(x);
    1021              : }
    1022              : 
    1023              : template <class T>
    1024              : constexpr bool operator>(nullopt_t, const optional<T>&) noexcept {
    1025              :   return false;
    1026              : }
    1027              : 
    1028              : template <class T>
    1029              : constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept {
    1030              :   return true;
    1031              : }
    1032              : 
    1033              : template <class T>
    1034              : constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept {
    1035              :   return (!x);
    1036              : }
    1037              : 
    1038              : // 20.5.10, Comparison with T
    1039              : template <class T, class U>
    1040              : constexpr bool operator==(const optional<T>& x, const U& v) {
    1041              :   return bool(x) ? *x == v : false;
    1042              : }
    1043              : 
    1044              : template <class T, class U>
    1045              : constexpr bool operator==(const U& v, const optional<T>& x) {
    1046              :   return bool(x) ? v == *x : false;
    1047              : }
    1048              : 
    1049              : template <class T, class U>
    1050              : constexpr bool operator!=(const optional<T>& x, const U& v) {
    1051              :   return bool(x) ? *x != v : true;
    1052              : }
    1053              : 
    1054              : template <class T, class U>
    1055              : constexpr bool operator!=(const U& v, const optional<T>& x) {
    1056              :   return bool(x) ? v != *x : true;
    1057              : }
    1058              : 
    1059              : template <class T, class U>
    1060              : constexpr bool operator<(const optional<T>& x, const U& v) {
    1061              :   return bool(x) ? *x < v : true;
    1062              : }
    1063              : 
    1064              : template <class T, class U>
    1065              : constexpr bool operator>(const U& v, const optional<T>& x) {
    1066              :   return bool(x) ? v > *x : true;
    1067              : }
    1068              : 
    1069              : template <class T, class U>
    1070              : constexpr bool operator>(const optional<T>& x, const U& v) {
    1071              :   return bool(x) ? *x > v : false;
    1072              : }
    1073              : 
    1074              : template <class T, class U>
    1075              : constexpr bool operator<(const U& v, const optional<T>& x) {
    1076              :   return bool(x) ? v < *x : false;
    1077              : }
    1078              : 
    1079              : template <class T, class U>
    1080              : constexpr bool operator>=(const optional<T>& x, const U& v) {
    1081              :   return bool(x) ? *x >= v : false;
    1082              : }
    1083              : 
    1084              : template <class T, class U>
    1085              : constexpr bool operator<=(const U& v, const optional<T>& x) {
    1086              :   return bool(x) ? v <= *x : false;
    1087              : }
    1088              : 
    1089              : template <class T, class U>
    1090              : constexpr bool operator<=(const optional<T>& x, const U& v) {
    1091              :   return bool(x) ? *x <= v : true;
    1092              : }
    1093              : 
    1094              : template <class T, class U>
    1095              : constexpr bool operator>=(const U& v, const optional<T>& x) {
    1096              :   return bool(x) ? v >= *x : true;
    1097              : }
    1098              : 
    1099              : // Comparison of optional<T&> with T
    1100              : template <class T>
    1101              : constexpr bool operator==(const optional<T&>& x, const T& v) {
    1102              :   return bool(x) ? *x == v : false;
    1103              : }
    1104              : 
    1105              : template <class T>
    1106              : constexpr bool operator==(const T& v, const optional<T&>& x) {
    1107              :   return bool(x) ? v == *x : false;
    1108              : }
    1109              : 
    1110              : template <class T>
    1111              : constexpr bool operator!=(const optional<T&>& x, const T& v) {
    1112              :   return bool(x) ? *x != v : true;
    1113              : }
    1114              : 
    1115              : template <class T>
    1116              : constexpr bool operator!=(const T& v, const optional<T&>& x) {
    1117              :   return bool(x) ? v != *x : true;
    1118              : }
    1119              : 
    1120              : template <class T>
    1121              : constexpr bool operator<(const optional<T&>& x, const T& v) {
    1122              :   return bool(x) ? *x < v : true;
    1123              : }
    1124              : 
    1125              : template <class T>
    1126              : constexpr bool operator>(const T& v, const optional<T&>& x) {
    1127              :   return bool(x) ? v > *x : true;
    1128              : }
    1129              : 
    1130              : template <class T>
    1131              : constexpr bool operator>(const optional<T&>& x, const T& v) {
    1132              :   return bool(x) ? *x > v : false;
    1133              : }
    1134              : 
    1135              : template <class T>
    1136              : constexpr bool operator<(const T& v, const optional<T&>& x) {
    1137              :   return bool(x) ? v < *x : false;
    1138              : }
    1139              : 
    1140              : template <class T>
    1141              : constexpr bool operator>=(const optional<T&>& x, const T& v) {
    1142              :   return bool(x) ? *x >= v : false;
    1143              : }
    1144              : 
    1145              : template <class T>
    1146              : constexpr bool operator<=(const T& v, const optional<T&>& x) {
    1147              :   return bool(x) ? v <= *x : false;
    1148              : }
    1149              : 
    1150              : template <class T>
    1151              : constexpr bool operator<=(const optional<T&>& x, const T& v) {
    1152              :   return bool(x) ? *x <= v : true;
    1153              : }
    1154              : 
    1155              : template <class T>
    1156              : constexpr bool operator>=(const T& v, const optional<T&>& x) {
    1157              :   return bool(x) ? v >= *x : true;
    1158              : }
    1159              : 
    1160              : // Comparison of optional<T const&> with T
    1161              : template <class T>
    1162              : constexpr bool operator==(const optional<const T&>& x, const T& v) {
    1163              :   return bool(x) ? *x == v : false;
    1164              : }
    1165              : 
    1166              : template <class T>
    1167              : constexpr bool operator==(const T& v, const optional<const T&>& x) {
    1168              :   return bool(x) ? v == *x : false;
    1169              : }
    1170              : 
    1171              : template <class T>
    1172              : constexpr bool operator!=(const optional<const T&>& x, const T& v) {
    1173              :   return bool(x) ? *x != v : true;
    1174              : }
    1175              : 
    1176              : template <class T>
    1177              : constexpr bool operator!=(const T& v, const optional<const T&>& x) {
    1178              :   return bool(x) ? v != *x : true;
    1179              : }
    1180              : 
    1181              : template <class T>
    1182              : constexpr bool operator<(const optional<const T&>& x, const T& v) {
    1183              :   return bool(x) ? *x < v : true;
    1184              : }
    1185              : 
    1186              : template <class T>
    1187              : constexpr bool operator>(const T& v, const optional<const T&>& x) {
    1188              :   return bool(x) ? v > *x : true;
    1189              : }
    1190              : 
    1191              : template <class T>
    1192              : constexpr bool operator>(const optional<const T&>& x, const T& v) {
    1193              :   return bool(x) ? *x > v : false;
    1194              : }
    1195              : 
    1196              : template <class T>
    1197              : constexpr bool operator<(const T& v, const optional<const T&>& x) {
    1198              :   return bool(x) ? v < *x : false;
    1199              : }
    1200              : 
    1201              : template <class T>
    1202              : constexpr bool operator>=(const optional<const T&>& x, const T& v) {
    1203              :   return bool(x) ? *x >= v : false;
    1204              : }
    1205              : 
    1206              : template <class T>
    1207              : constexpr bool operator<=(const T& v, const optional<const T&>& x) {
    1208              :   return bool(x) ? v <= *x : false;
    1209              : }
    1210              : 
    1211              : template <class T>
    1212              : constexpr bool operator<=(const optional<const T&>& x, const T& v) {
    1213              :   return bool(x) ? *x <= v : true;
    1214              : }
    1215              : 
    1216              : template <class T>
    1217              : constexpr bool operator>=(const T& v, const optional<const T&>& x) {
    1218              :   return bool(x) ? v >= *x : true;
    1219              : }
    1220              : 
    1221              : // 20.5.12, Specialized algorithms
    1222              : template <class T>
    1223              : void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y))) {
    1224              :   x.swap(y);
    1225              : }
    1226              : 
    1227              : template <class T>
    1228       418776 : constexpr optional<typename std::decay<T>::type> make_optional(T&& v) {
    1229       418776 :   return optional<typename std::decay<T>::type>(constexpr_forward<T>(v));
    1230              : }
    1231              : 
    1232              : template <class X>
    1233              : constexpr optional<X&> make_optional(std::reference_wrapper<X> v) {
    1234              :   return optional<X&>(v.get());
    1235              : }
    1236              : 
    1237              : } // namespace c10
    1238              : 
    1239              : namespace std {
    1240              : template <typename T>
    1241              : struct hash<c10::optional<T>> {
    1242              :   typedef c10::invoke_result_t<std::hash<T>, T> result_type;
    1243              :   typedef c10::optional<T> argument_type;
    1244              : 
    1245              :   constexpr result_type operator()(argument_type const& arg) const {
    1246              :     return arg ? std::hash<T>{}(*arg) : result_type{};
    1247              :   }
    1248              : };
    1249              : 
    1250              : template <typename T>
    1251              : struct hash<c10::optional<T&>> {
    1252              :   typedef typename hash<T>::result_type result_type;
    1253              :   typedef c10::optional<T&> argument_type;
    1254              : 
    1255              :   constexpr result_type operator()(argument_type const& arg) const {
    1256              :     return arg ? std::hash<T>{}(*arg) : result_type{};
    1257              :   }
    1258              : };
    1259              : } // namespace std
    1260              : 
    1261              : #undef TR2_OPTIONAL_REQUIRES
    1262              : #undef TR2_OPTIONAL_ASSERTED_EXPRESSION
    1263              : #undef TR2_OPTIONAL_HOST_CONSTEXPR
    1264              : 
    1265              : C10_CLANG_DIAGNOSTIC_POP()
    1266              : 
    1267              : #if defined(_MSC_VER) && !defined(__clang__)
    1268              : #pragma warning(pop)
    1269              : #endif
    1270              : 
    1271              : #endif // C10_UTIL_OPTIONAL_H_
        

Generated by: LCOV version 2.0-1

</html>