libstdc++
|
00001 // <optional> -*- C++ -*- 00002 00003 // Copyright (C) 2013-2015 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 3, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // Under Section 7 of GPL version 3, you are granted additional 00017 // permissions described in the GCC Runtime Library Exception, version 00018 // 3.1, as published by the Free Software Foundation. 00019 00020 // You should have received a copy of the GNU General Public License and 00021 // a copy of the GCC Runtime Library Exception along with this program; 00022 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00023 // <http://www.gnu.org/licenses/>. 00024 00025 /** @file experimental/optional 00026 * This is a TS C++ Library header. 00027 */ 00028 00029 #ifndef _GLIBCXX_EXPERIMENTAL_OPTIONAL 00030 #define _GLIBCXX_EXPERIMENTAL_OPTIONAL 1 00031 00032 /** 00033 * @defgroup experimental Experimental 00034 * 00035 * Components specified by various Technical Specifications. 00036 */ 00037 00038 #if __cplusplus <= 201103L 00039 # include <bits/c++14_warning.h> 00040 #else 00041 00042 #include <utility> 00043 #include <type_traits> 00044 #include <stdexcept> 00045 #include <new> 00046 #include <initializer_list> 00047 #include <bits/functexcept.h> 00048 #include <bits/functional_hash.h> 00049 #include <bits/enable_special_members.h> 00050 00051 namespace std _GLIBCXX_VISIBILITY(default) 00052 { 00053 namespace experimental 00054 { 00055 inline namespace fundamentals_v1 00056 { 00057 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00058 00059 /** 00060 * @defgroup optional Optional values 00061 * @ingroup experimental 00062 * 00063 * Class template for optional values and surrounding facilities, as 00064 * described in n3793 "A proposal to add a utility class to represent 00065 * optional objects (Revision 5)". 00066 * 00067 * @{ 00068 */ 00069 00070 #define __cpp_lib_experimental_optional 201411 00071 00072 // All subsequent [X.Y.n] references are against n3793. 00073 00074 // [X.Y.4] 00075 template<typename _Tp> 00076 class optional; 00077 00078 // [X.Y.5] 00079 /// Tag type for in-place construction. 00080 struct in_place_t { }; 00081 00082 /// Tag for in-place construction. 00083 constexpr in_place_t in_place { }; 00084 00085 // [X.Y.6] 00086 /// Tag type to disengage optional objects. 00087 struct nullopt_t 00088 { 00089 // Do not user-declare default constructor at all for 00090 // optional_value = {} syntax to work. 00091 // nullopt_t() = delete; 00092 00093 // Used for constructing nullopt. 00094 enum class _Construct { _Token }; 00095 00096 // Must be constexpr for nullopt_t to be literal. 00097 explicit constexpr nullopt_t(_Construct) { } 00098 }; 00099 00100 // [X.Y.6] 00101 /// Tag to disengage optional objects. 00102 constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token }; 00103 00104 // [X.Y.7] 00105 /** 00106 * @brief Exception class thrown when a disengaged optional object is 00107 * dereferenced. 00108 * @ingroup exceptions 00109 */ 00110 class bad_optional_access : public logic_error 00111 { 00112 public: 00113 bad_optional_access() : logic_error("bad optional access") { } 00114 00115 // XXX This constructor is non-standard. Should not be inline 00116 explicit bad_optional_access(const char* __arg) : logic_error(__arg) { } 00117 00118 virtual ~bad_optional_access() noexcept = default; 00119 }; 00120 00121 void 00122 __throw_bad_optional_access(const char*) 00123 __attribute__((__noreturn__)); 00124 00125 // XXX Does not belong here. 00126 inline void 00127 __throw_bad_optional_access(const char* __s) 00128 { _GLIBCXX_THROW_OR_ABORT(bad_optional_access(__s)); } 00129 00130 template<typename _Tp, typename = void> 00131 struct _Has_addressof_mem : std::false_type { }; 00132 00133 template<typename _Tp> 00134 struct _Has_addressof_mem<_Tp, 00135 __void_t<decltype( std::declval<const _Tp&>().operator&() )> 00136 > 00137 : std::true_type { }; 00138 00139 template<typename _Tp, typename = void> 00140 struct _Has_addressof_free : std::false_type { }; 00141 00142 template<typename _Tp> 00143 struct _Has_addressof_free<_Tp, 00144 __void_t<decltype( operator&(std::declval<const _Tp&>()) )> 00145 > 00146 : std::true_type { }; 00147 00148 /** 00149 * @brief Trait that detects the presence of an overloaded unary operator&. 00150 * 00151 * Practically speaking this detects the presence of such an operator when 00152 * called on a const-qualified lvalue (i.e. 00153 * declval<_Tp * const&>().operator&()). 00154 */ 00155 template<typename _Tp> 00156 struct _Has_addressof 00157 : std::__or_<_Has_addressof_mem<_Tp>, _Has_addressof_free<_Tp>>::type 00158 { }; 00159 00160 /** 00161 * @brief An overload that attempts to take the address of an lvalue as a 00162 * constant expression. Falls back to __addressof in the presence of an 00163 * overloaded addressof operator (unary operator&), in which case the call 00164 * will not be a constant expression. 00165 */ 00166 template<typename _Tp, enable_if_t<!_Has_addressof<_Tp>::value, int>...> 00167 constexpr _Tp* __constexpr_addressof(_Tp& __t) 00168 { return &__t; } 00169 00170 /** 00171 * @brief Fallback overload that defers to __addressof. 00172 */ 00173 template<typename _Tp, enable_if_t<_Has_addressof<_Tp>::value, int>...> 00174 inline _Tp* __constexpr_addressof(_Tp& __t) 00175 { return std::__addressof(__t); } 00176 00177 /** 00178 * @brief Class template that holds the necessary state for @ref optional 00179 * and that has the responsibility for construction and the special members. 00180 * 00181 * Such a separate base class template is necessary in order to 00182 * conditionally enable the special members (e.g. copy/move constructors). 00183 * Note that this means that @ref _Optional_base implements the 00184 * functionality for copy and move assignment, but not for converting 00185 * assignment. 00186 * 00187 * @see optional, _Enable_special_members 00188 */ 00189 template<typename _Tp, bool _ShouldProvideDestructor = 00190 !is_trivially_destructible<_Tp>::value> 00191 class _Optional_base 00192 { 00193 private: 00194 // Remove const to avoid prohibition of reusing object storage for 00195 // const-qualified types in [3.8/9]. This is strictly internal 00196 // and even optional itself is oblivious to it. 00197 using _Stored_type = remove_const_t<_Tp>; 00198 00199 public: 00200 // [X.Y.4.1] Constructors. 00201 00202 // Constructors for disengaged optionals. 00203 constexpr _Optional_base() noexcept 00204 : _M_empty{} { } 00205 00206 constexpr _Optional_base(nullopt_t) noexcept 00207 : _Optional_base{} { } 00208 00209 // Constructors for engaged optionals. 00210 constexpr _Optional_base(const _Tp& __t) 00211 : _M_payload(__t), _M_engaged(true) { } 00212 00213 constexpr _Optional_base(_Tp&& __t) 00214 : _M_payload(std::move(__t)), _M_engaged(true) { } 00215 00216 template<typename... _Args> 00217 constexpr explicit _Optional_base(in_place_t, _Args&&... __args) 00218 : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { } 00219 00220 template<typename _Up, typename... _Args, 00221 enable_if_t<is_constructible<_Tp, 00222 initializer_list<_Up>&, 00223 _Args&&...>::value, 00224 int>...> 00225 constexpr explicit _Optional_base(in_place_t, 00226 initializer_list<_Up> __il, 00227 _Args&&... __args) 00228 : _M_payload(__il, std::forward<_Args>(__args)...), 00229 _M_engaged(true) { } 00230 00231 // Copy and move constructors. 00232 _Optional_base(const _Optional_base& __other) 00233 { 00234 if (__other._M_engaged) 00235 this->_M_construct(__other._M_get()); 00236 } 00237 00238 _Optional_base(_Optional_base&& __other) 00239 noexcept(is_nothrow_move_constructible<_Tp>()) 00240 { 00241 if (__other._M_engaged) 00242 this->_M_construct(std::move(__other._M_get())); 00243 } 00244 00245 // [X.Y.4.3] (partly) Assignment. 00246 _Optional_base& 00247 operator=(const _Optional_base& __other) 00248 { 00249 if (this->_M_engaged && __other._M_engaged) 00250 this->_M_get() = __other._M_get(); 00251 else 00252 { 00253 if (__other._M_engaged) 00254 this->_M_construct(__other._M_get()); 00255 else 00256 this->_M_reset(); 00257 } 00258 00259 return *this; 00260 } 00261 00262 _Optional_base& 00263 operator=(_Optional_base&& __other) 00264 noexcept(__and_<is_nothrow_move_constructible<_Tp>, 00265 is_nothrow_move_assignable<_Tp>>()) 00266 { 00267 if (this->_M_engaged && __other._M_engaged) 00268 this->_M_get() = std::move(__other._M_get()); 00269 else 00270 { 00271 if (__other._M_engaged) 00272 this->_M_construct(std::move(__other._M_get())); 00273 else 00274 this->_M_reset(); 00275 } 00276 return *this; 00277 } 00278 00279 // [X.Y.4.2] Destructor. 00280 ~_Optional_base() 00281 { 00282 if (this->_M_engaged) 00283 this->_M_payload.~_Stored_type(); 00284 } 00285 00286 // The following functionality is also needed by optional, hence the 00287 // protected accessibility. 00288 protected: 00289 constexpr bool _M_is_engaged() const noexcept 00290 { return this->_M_engaged; } 00291 00292 // The _M_get operations have _M_engaged as a precondition. 00293 constexpr _Tp& 00294 _M_get() noexcept 00295 { return _M_payload; } 00296 00297 constexpr const _Tp& 00298 _M_get() const noexcept 00299 { return _M_payload; } 00300 00301 // The _M_construct operation has !_M_engaged as a precondition 00302 // while _M_destruct has _M_engaged as a precondition. 00303 template<typename... _Args> 00304 void 00305 _M_construct(_Args&&... __args) 00306 noexcept(is_nothrow_constructible<_Stored_type, _Args...>()) 00307 { 00308 ::new (std::__addressof(this->_M_payload)) 00309 _Stored_type(std::forward<_Args>(__args)...); 00310 this->_M_engaged = true; 00311 } 00312 00313 void 00314 _M_destruct() 00315 { 00316 this->_M_engaged = false; 00317 this->_M_payload.~_Stored_type(); 00318 } 00319 00320 // _M_reset is a 'safe' operation with no precondition. 00321 void 00322 _M_reset() 00323 { 00324 if (this->_M_engaged) 00325 this->_M_destruct(); 00326 } 00327 00328 private: 00329 struct _Empty_byte { }; 00330 union { 00331 _Empty_byte _M_empty; 00332 _Stored_type _M_payload; 00333 }; 00334 bool _M_engaged = false; 00335 }; 00336 00337 /// Partial specialization that is exactly identical to the primary template 00338 /// save for not providing a destructor, to fulfill triviality requirements. 00339 template<typename _Tp> 00340 class _Optional_base<_Tp, false> 00341 { 00342 private: 00343 using _Stored_type = remove_const_t<_Tp>; 00344 00345 public: 00346 constexpr _Optional_base() noexcept 00347 : _M_empty{} { } 00348 00349 constexpr _Optional_base(nullopt_t) noexcept 00350 : _Optional_base{} { } 00351 00352 constexpr _Optional_base(const _Tp& __t) 00353 : _M_payload(__t), _M_engaged(true) { } 00354 00355 constexpr _Optional_base(_Tp&& __t) 00356 : _M_payload(std::move(__t)), _M_engaged(true) { } 00357 00358 template<typename... _Args> 00359 constexpr explicit _Optional_base(in_place_t, _Args&&... __args) 00360 : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { } 00361 00362 template<typename _Up, typename... _Args, 00363 enable_if_t<is_constructible<_Tp, 00364 initializer_list<_Up>&, 00365 _Args&&...>::value, 00366 int>...> 00367 constexpr explicit _Optional_base(in_place_t, 00368 initializer_list<_Up> __il, 00369 _Args&&... __args) 00370 : _M_payload(__il, std::forward<_Args>(__args)...), 00371 _M_engaged(true) { } 00372 00373 _Optional_base(const _Optional_base& __other) 00374 { 00375 if (__other._M_engaged) 00376 this->_M_construct(__other._M_get()); 00377 } 00378 00379 _Optional_base(_Optional_base&& __other) 00380 noexcept(is_nothrow_move_constructible<_Tp>()) 00381 { 00382 if (__other._M_engaged) 00383 this->_M_construct(std::move(__other._M_get())); 00384 } 00385 00386 _Optional_base& 00387 operator=(const _Optional_base& __other) 00388 { 00389 if (this->_M_engaged && __other._M_engaged) 00390 this->_M_get() = __other._M_get(); 00391 else 00392 { 00393 if (__other._M_engaged) 00394 this->_M_construct(__other._M_get()); 00395 else 00396 this->_M_reset(); 00397 } 00398 return *this; 00399 } 00400 00401 _Optional_base& 00402 operator=(_Optional_base&& __other) 00403 noexcept(__and_<is_nothrow_move_constructible<_Tp>, 00404 is_nothrow_move_assignable<_Tp>>()) 00405 { 00406 if (this->_M_engaged && __other._M_engaged) 00407 this->_M_get() = std::move(__other._M_get()); 00408 else 00409 { 00410 if (__other._M_engaged) 00411 this->_M_construct(std::move(__other._M_get())); 00412 else 00413 this->_M_reset(); 00414 } 00415 return *this; 00416 } 00417 00418 // Sole difference 00419 // ~_Optional_base() noexcept = default; 00420 00421 protected: 00422 constexpr bool _M_is_engaged() const noexcept 00423 { return this->_M_engaged; } 00424 00425 _Tp& 00426 _M_get() noexcept 00427 { return _M_payload; } 00428 00429 constexpr const _Tp& 00430 _M_get() const noexcept 00431 { return _M_payload; } 00432 00433 template<typename... _Args> 00434 void 00435 _M_construct(_Args&&... __args) 00436 noexcept(is_nothrow_constructible<_Stored_type, _Args...>()) 00437 { 00438 ::new (std::__addressof(this->_M_payload)) 00439 _Stored_type(std::forward<_Args>(__args)...); 00440 this->_M_engaged = true; 00441 } 00442 00443 void 00444 _M_destruct() 00445 { 00446 this->_M_engaged = false; 00447 this->_M_payload.~_Stored_type(); 00448 } 00449 00450 void 00451 _M_reset() 00452 { 00453 if (this->_M_engaged) 00454 this->_M_destruct(); 00455 } 00456 00457 private: 00458 struct _Empty_byte { }; 00459 union 00460 { 00461 _Empty_byte _M_empty; 00462 _Stored_type _M_payload; 00463 }; 00464 bool _M_engaged = false; 00465 }; 00466 00467 /** 00468 * @brief Class template for optional values. 00469 */ 00470 template<typename _Tp> 00471 class optional 00472 : private _Optional_base<_Tp>, 00473 private _Enable_copy_move< 00474 // Copy constructor. 00475 is_copy_constructible<_Tp>::value, 00476 // Copy assignment. 00477 __and_<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>::value, 00478 // Move constructor. 00479 is_move_constructible<_Tp>::value, 00480 // Move assignment. 00481 __and_<is_move_constructible<_Tp>, is_move_assignable<_Tp>>::value, 00482 // Unique tag type. 00483 optional<_Tp>> 00484 { 00485 static_assert(__and_<__not_<is_same<remove_cv_t<_Tp>, nullopt_t>>, 00486 __not_<is_same<remove_cv_t<_Tp>, in_place_t>>, 00487 __not_<is_reference<_Tp>>>(), 00488 "Invalid instantiation of optional<T>"); 00489 00490 private: 00491 using _Base = _Optional_base<_Tp>; 00492 00493 public: 00494 using value_type = _Tp; 00495 00496 // _Optional_base has the responsibility for construction. 00497 using _Base::_Base; 00498 00499 // [X.Y.4.3] (partly) Assignment. 00500 optional& 00501 operator=(nullopt_t) noexcept 00502 { 00503 this->_M_reset(); 00504 return *this; 00505 } 00506 00507 template<typename _Up> 00508 enable_if_t<is_same<_Tp, decay_t<_Up>>::value, optional&> 00509 operator=(_Up&& __u) 00510 { 00511 static_assert(__and_<is_constructible<_Tp, _Up>, 00512 is_assignable<_Tp&, _Up>>(), 00513 "Cannot assign to value type from argument"); 00514 00515 if (this->_M_is_engaged()) 00516 this->_M_get() = std::forward<_Up>(__u); 00517 else 00518 this->_M_construct(std::forward<_Up>(__u)); 00519 00520 return *this; 00521 } 00522 00523 template<typename... _Args> 00524 void 00525 emplace(_Args&&... __args) 00526 { 00527 static_assert(is_constructible<_Tp, _Args&&...>(), 00528 "Cannot emplace value type from arguments"); 00529 00530 this->_M_reset(); 00531 this->_M_construct(std::forward<_Args>(__args)...); 00532 } 00533 00534 template<typename _Up, typename... _Args> 00535 enable_if_t<is_constructible<_Tp, initializer_list<_Up>&, 00536 _Args&&...>::value> 00537 emplace(initializer_list<_Up> __il, _Args&&... __args) 00538 { 00539 this->_M_reset(); 00540 this->_M_construct(__il, std::forward<_Args>(__args)...); 00541 } 00542 00543 // [X.Y.4.2] Destructor is implicit, implemented in _Optional_base. 00544 00545 // [X.Y.4.4] Swap. 00546 void 00547 swap(optional& __other) 00548 noexcept(is_nothrow_move_constructible<_Tp>() 00549 && noexcept(swap(declval<_Tp&>(), declval<_Tp&>()))) 00550 { 00551 using std::swap; 00552 00553 if (this->_M_is_engaged() && __other._M_is_engaged()) 00554 swap(this->_M_get(), __other._M_get()); 00555 else if (this->_M_is_engaged()) 00556 { 00557 __other._M_construct(std::move(this->_M_get())); 00558 this->_M_destruct(); 00559 } 00560 else if (__other._M_is_engaged()) 00561 { 00562 this->_M_construct(std::move(__other._M_get())); 00563 __other._M_destruct(); 00564 } 00565 } 00566 00567 // [X.Y.4.5] Observers. 00568 constexpr const _Tp* 00569 operator->() const 00570 { return __constexpr_addressof(this->_M_get()); } 00571 00572 _Tp* 00573 operator->() 00574 { return std::__addressof(this->_M_get()); } 00575 00576 constexpr const _Tp& 00577 operator*() const& 00578 { return this->_M_get(); } 00579 00580 constexpr _Tp& 00581 operator*()& 00582 { return this->_M_get(); } 00583 00584 constexpr _Tp&& 00585 operator*()&& 00586 { return std::move(this->_M_get()); } 00587 00588 constexpr const _Tp&& 00589 operator*() const&& 00590 { return std::move(this->_M_get()); } 00591 00592 constexpr explicit operator bool() const noexcept 00593 { return this->_M_is_engaged(); } 00594 00595 constexpr const _Tp& 00596 value() const& 00597 { 00598 return this->_M_is_engaged() 00599 ? this->_M_get() 00600 : (__throw_bad_optional_access("Attempt to access value of a " 00601 "disengaged optional object"), 00602 this->_M_get()); 00603 } 00604 00605 constexpr _Tp& 00606 value()& 00607 { 00608 return this->_M_is_engaged() 00609 ? this->_M_get() 00610 : (__throw_bad_optional_access("Attempt to access value of a " 00611 "disengaged optional object"), 00612 this->_M_get()); 00613 } 00614 00615 constexpr _Tp&& 00616 value()&& 00617 { 00618 return this->_M_is_engaged() 00619 ? std::move(this->_M_get()) 00620 : (__throw_bad_optional_access("Attempt to access value of a " 00621 "disengaged optional object"), 00622 std::move(this->_M_get())); 00623 } 00624 00625 constexpr const _Tp&& 00626 value() const&& 00627 { 00628 return this->_M_is_engaged() 00629 ? std::move(this->_M_get()) 00630 : (__throw_bad_optional_access("Attempt to access value of a " 00631 "disengaged optional object"), 00632 std::move(this->_M_get())); 00633 } 00634 00635 template<typename _Up> 00636 constexpr _Tp 00637 value_or(_Up&& __u) const& 00638 { 00639 static_assert(__and_<is_copy_constructible<_Tp>, 00640 is_convertible<_Up&&, _Tp>>(), 00641 "Cannot return value"); 00642 00643 return this->_M_is_engaged() 00644 ? this->_M_get() 00645 : static_cast<_Tp>(std::forward<_Up>(__u)); 00646 } 00647 00648 template<typename _Up> 00649 _Tp 00650 value_or(_Up&& __u) && 00651 { 00652 static_assert(__and_<is_move_constructible<_Tp>, 00653 is_convertible<_Up&&, _Tp>>(), 00654 "Cannot return value" ); 00655 00656 return this->_M_is_engaged() 00657 ? std::move(this->_M_get()) 00658 : static_cast<_Tp>(std::forward<_Up>(__u)); 00659 } 00660 }; 00661 00662 // [X.Y.8] Comparisons between optional values. 00663 template<typename _Tp> 00664 constexpr bool 00665 operator==(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 00666 { 00667 return static_cast<bool>(__lhs) == static_cast<bool>(__rhs) 00668 && (!__lhs || *__lhs == *__rhs); 00669 } 00670 00671 template<typename _Tp> 00672 constexpr bool 00673 operator!=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 00674 { return !(__lhs == __rhs); } 00675 00676 template<typename _Tp> 00677 constexpr bool 00678 operator<(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 00679 { 00680 return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs); 00681 } 00682 00683 template<typename _Tp> 00684 constexpr bool 00685 operator>(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 00686 { return __rhs < __lhs; } 00687 00688 template<typename _Tp> 00689 constexpr bool 00690 operator<=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 00691 { return !(__rhs < __lhs); } 00692 00693 template<typename _Tp> 00694 constexpr bool 00695 operator>=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 00696 { return !(__lhs < __rhs); } 00697 00698 // [X.Y.9] Comparisons with nullopt. 00699 template<typename _Tp> 00700 constexpr bool 00701 operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept 00702 { return !__lhs; } 00703 00704 template<typename _Tp> 00705 constexpr bool 00706 operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept 00707 { return !__rhs; } 00708 00709 template<typename _Tp> 00710 constexpr bool 00711 operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept 00712 { return static_cast<bool>(__lhs); } 00713 00714 template<typename _Tp> 00715 constexpr bool 00716 operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept 00717 { return static_cast<bool>(__rhs); } 00718 00719 template<typename _Tp> 00720 constexpr bool 00721 operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept 00722 { return false; } 00723 00724 template<typename _Tp> 00725 constexpr bool 00726 operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept 00727 { return static_cast<bool>(__rhs); } 00728 00729 template<typename _Tp> 00730 constexpr bool 00731 operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept 00732 { return static_cast<bool>(__lhs); } 00733 00734 template<typename _Tp> 00735 constexpr bool 00736 operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept 00737 { return false; } 00738 00739 template<typename _Tp> 00740 constexpr bool 00741 operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept 00742 { return !__lhs; } 00743 00744 template<typename _Tp> 00745 constexpr bool 00746 operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept 00747 { return true; } 00748 00749 template<typename _Tp> 00750 constexpr bool 00751 operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept 00752 { return true; } 00753 00754 template<typename _Tp> 00755 constexpr bool 00756 operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept 00757 { return !__rhs; } 00758 00759 // [X.Y.10] Comparisons with value type. 00760 template<typename _Tp> 00761 constexpr bool 00762 operator==(const optional<_Tp>& __lhs, const _Tp& __rhs) 00763 { return __lhs && *__lhs == __rhs; } 00764 00765 template<typename _Tp> 00766 constexpr bool 00767 operator==(const _Tp& __lhs, const optional<_Tp>& __rhs) 00768 { return __rhs && __lhs == *__rhs; } 00769 00770 template<typename _Tp> 00771 constexpr bool 00772 operator!=(const optional<_Tp>& __lhs, _Tp const& __rhs) 00773 { return !__lhs || !(*__lhs == __rhs); } 00774 00775 template<typename _Tp> 00776 constexpr bool 00777 operator!=(const _Tp& __lhs, const optional<_Tp>& __rhs) 00778 { return !__rhs || !(__lhs == *__rhs); } 00779 00780 template<typename _Tp> 00781 constexpr bool 00782 operator<(const optional<_Tp>& __lhs, const _Tp& __rhs) 00783 { return !__lhs || *__lhs < __rhs; } 00784 00785 template<typename _Tp> 00786 constexpr bool 00787 operator<(const _Tp& __lhs, const optional<_Tp>& __rhs) 00788 { return __rhs && __lhs < *__rhs; } 00789 00790 template<typename _Tp> 00791 constexpr bool 00792 operator>(const optional<_Tp>& __lhs, const _Tp& __rhs) 00793 { return __lhs && __rhs < *__lhs; } 00794 00795 template<typename _Tp> 00796 constexpr bool 00797 operator>(const _Tp& __lhs, const optional<_Tp>& __rhs) 00798 { return !__rhs || *__rhs < __lhs; } 00799 00800 template<typename _Tp> 00801 constexpr bool 00802 operator<=(const optional<_Tp>& __lhs, const _Tp& __rhs) 00803 { return !__lhs || !(__rhs < *__lhs); } 00804 00805 template<typename _Tp> 00806 constexpr bool 00807 operator<=(const _Tp& __lhs, const optional<_Tp>& __rhs) 00808 { return __rhs && !(*__rhs < __lhs); } 00809 00810 template<typename _Tp> 00811 constexpr bool 00812 operator>=(const optional<_Tp>& __lhs, const _Tp& __rhs) 00813 { return __lhs && !(*__lhs < __rhs); } 00814 00815 template<typename _Tp> 00816 constexpr bool 00817 operator>=(const _Tp& __lhs, const optional<_Tp>& __rhs) 00818 { return !__rhs || !(__lhs < *__rhs); } 00819 00820 // [X.Y.11] 00821 template<typename _Tp> 00822 inline void 00823 swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs) 00824 noexcept(noexcept(__lhs.swap(__rhs))) 00825 { __lhs.swap(__rhs); } 00826 00827 template<typename _Tp> 00828 constexpr optional<decay_t<_Tp>> 00829 make_optional(_Tp&& __t) 00830 { return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; } 00831 00832 // @} group optional 00833 _GLIBCXX_END_NAMESPACE_VERSION 00834 } // namespace fundamentals_v1 00835 } 00836 00837 // [X.Y.12] 00838 template<typename _Tp> 00839 struct hash<experimental::optional<_Tp>> 00840 { 00841 using result_type = size_t; 00842 using argument_type = experimental::optional<_Tp>; 00843 00844 size_t 00845 operator()(const experimental::optional<_Tp>& __t) const 00846 noexcept(noexcept(hash<_Tp> {}(*__t))) 00847 { 00848 // We pick an arbitrary hash for disengaged optionals which hopefully 00849 // usual values of _Tp won't typically hash to. 00850 constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333); 00851 return __t ? hash<_Tp> {}(*__t) : __magic_disengaged_hash; 00852 } 00853 }; 00854 } 00855 00856 #endif // C++14 00857 00858 #endif // _GLIBCXX_EXPERIMENTAL_OPTIONAL