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