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