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