libstdc++
|
00001 // <optional> -*- C++ -*- 00002 00003 // Copyright (C) 2013-2016 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 template<typename _Tp> 00474 class optional; 00475 00476 template<typename> 00477 struct __is_optional_impl : false_type 00478 { }; 00479 00480 template<typename _Tp> 00481 struct __is_optional_impl<optional<_Tp>> : true_type 00482 { }; 00483 00484 template<typename _Tp> 00485 struct __is_optional 00486 : public __is_optional_impl<std::remove_cv_t<std::remove_reference_t<_Tp>>> 00487 { }; 00488 00489 00490 /** 00491 * @brief Class template for optional values. 00492 */ 00493 template<typename _Tp> 00494 class optional 00495 : private _Optional_base<_Tp>, 00496 private _Enable_copy_move< 00497 // Copy constructor. 00498 is_copy_constructible<_Tp>::value, 00499 // Copy assignment. 00500 __and_<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>::value, 00501 // Move constructor. 00502 is_move_constructible<_Tp>::value, 00503 // Move assignment. 00504 __and_<is_move_constructible<_Tp>, is_move_assignable<_Tp>>::value, 00505 // Unique tag type. 00506 optional<_Tp>> 00507 { 00508 static_assert(__and_<__not_<is_same<remove_cv_t<_Tp>, nullopt_t>>, 00509 __not_<is_same<remove_cv_t<_Tp>, in_place_t>>, 00510 __not_<is_reference<_Tp>>>(), 00511 "Invalid instantiation of optional<T>"); 00512 00513 private: 00514 using _Base = _Optional_base<_Tp>; 00515 00516 public: 00517 using value_type = _Tp; 00518 00519 // _Optional_base has the responsibility for construction. 00520 using _Base::_Base; 00521 00522 constexpr optional() = default; 00523 // Converting constructors for engaged optionals. 00524 template <typename _Up, 00525 enable_if_t<__and_< 00526 __not_<is_same<_Tp, _Up>>, 00527 is_constructible<_Tp, _Up&&>, 00528 is_convertible<_Up&&, _Tp> 00529 >::value, bool> = true> 00530 constexpr optional(_Up&& __t) 00531 : _Base(_Tp(std::forward<_Up>(__t))) { } 00532 00533 template <typename _Up, 00534 enable_if_t<__and_< 00535 __not_<is_same<_Tp, _Up>>, 00536 is_constructible<_Tp, _Up&&>, 00537 __not_<is_convertible<_Up&&, _Tp>> 00538 >::value, bool> = false> 00539 explicit constexpr optional(_Up&& __t) 00540 : _Base(_Tp(std::forward<_Up>(__t))) { } 00541 00542 template <typename _Up, 00543 enable_if_t<__and_< 00544 __not_<is_same<_Tp, _Up>>, 00545 __not_<is_constructible< 00546 _Tp, const optional<_Up>&>>, 00547 __not_<is_convertible< 00548 const optional<_Up>&, _Tp>>, 00549 is_constructible<_Tp, const _Up&>, 00550 is_convertible<const _Up&, _Tp> 00551 >::value, bool> = true> 00552 constexpr optional(const optional<_Up>& __t) 00553 : _Base(__t ? optional<_Tp>(*__t) : optional<_Tp>()) { } 00554 00555 template <typename _Up, 00556 enable_if_t<__and_< 00557 __not_<is_same<_Tp, _Up>>, 00558 __not_<is_constructible< 00559 _Tp, const optional<_Up>&>>, 00560 __not_<is_convertible< 00561 const optional<_Up>&, _Tp>>, 00562 is_constructible<_Tp, const _Up&>, 00563 __not_<is_convertible<const _Up&, _Tp>> 00564 >::value, bool> = false> 00565 explicit constexpr optional(const optional<_Up>& __t) 00566 : _Base(__t ? optional<_Tp>(*__t) : optional<_Tp>()) { } 00567 00568 template <typename _Up, 00569 enable_if_t<__and_< 00570 __not_<is_same<_Tp, _Up>>, 00571 __not_<is_constructible< 00572 _Tp, optional<_Up>&&>>, 00573 __not_<is_convertible< 00574 optional<_Up>&&, _Tp>>, 00575 is_constructible<_Tp, _Up&&>, 00576 is_convertible<_Up&&, _Tp> 00577 >::value, bool> = true> 00578 constexpr optional(optional<_Up>&& __t) 00579 : _Base(__t ? optional<_Tp>(std::move(*__t)) : optional<_Tp>()) { } 00580 00581 template <typename _Up, 00582 enable_if_t<__and_< 00583 __not_<is_same<_Tp, _Up>>, 00584 __not_<is_constructible< 00585 _Tp, optional<_Up>&&>>, 00586 __not_<is_convertible< 00587 optional<_Up>&&, _Tp>>, 00588 is_constructible<_Tp, _Up&&>, 00589 __not_<is_convertible<_Up&&, _Tp>> 00590 >::value, bool> = false> 00591 explicit constexpr optional(optional<_Up>&& __t) 00592 : _Base(__t ? optional<_Tp>(std::move(*__t)) : optional<_Tp>()) { } 00593 00594 // [X.Y.4.3] (partly) Assignment. 00595 optional& 00596 operator=(nullopt_t) noexcept 00597 { 00598 this->_M_reset(); 00599 return *this; 00600 } 00601 00602 template<typename _Up, 00603 enable_if_t<__and_< 00604 __not_<is_same<_Up, nullopt_t>>, 00605 __not_<__is_optional<_Up>>>::value, 00606 bool> = true> 00607 optional& 00608 operator=(_Up&& __u) 00609 { 00610 static_assert(__and_<is_constructible<_Tp, _Up>, 00611 is_assignable<_Tp&, _Up>>(), 00612 "Cannot assign to value type from argument"); 00613 00614 if (this->_M_is_engaged()) 00615 this->_M_get() = std::forward<_Up>(__u); 00616 else 00617 this->_M_construct(std::forward<_Up>(__u)); 00618 00619 return *this; 00620 } 00621 00622 template<typename _Up, 00623 enable_if_t<__and_< 00624 __not_<is_same<_Tp, _Up>>>::value, 00625 bool> = true> 00626 optional& 00627 operator=(const optional<_Up>& __u) 00628 { 00629 static_assert(__and_<is_constructible<_Tp, _Up>, 00630 is_assignable<_Tp&, _Up>>(), 00631 "Cannot assign to value type from argument"); 00632 00633 if (__u) 00634 { 00635 if (this->_M_is_engaged()) 00636 this->_M_get() = *__u; 00637 else 00638 this->_M_construct(*__u); 00639 } 00640 else 00641 { 00642 this->_M_reset(); 00643 } 00644 return *this; 00645 } 00646 00647 template<typename _Up, 00648 enable_if_t<__and_< 00649 __not_<is_same<_Tp, _Up>>>::value, 00650 bool> = true> 00651 optional& 00652 operator=(optional<_Up>&& __u) 00653 { 00654 static_assert(__and_<is_constructible<_Tp, _Up>, 00655 is_assignable<_Tp&, _Up>>(), 00656 "Cannot assign to value type from argument"); 00657 00658 if (__u) 00659 { 00660 if (this->_M_is_engaged()) 00661 this->_M_get() = std::move(*__u); 00662 else 00663 this->_M_construct(std::move(*__u)); 00664 } 00665 else 00666 { 00667 this->_M_reset(); 00668 } 00669 00670 return *this; 00671 } 00672 00673 template<typename... _Args> 00674 void 00675 emplace(_Args&&... __args) 00676 { 00677 static_assert(is_constructible<_Tp, _Args&&...>(), 00678 "Cannot emplace value type from arguments"); 00679 00680 this->_M_reset(); 00681 this->_M_construct(std::forward<_Args>(__args)...); 00682 } 00683 00684 template<typename _Up, typename... _Args> 00685 enable_if_t<is_constructible<_Tp, initializer_list<_Up>&, 00686 _Args&&...>::value> 00687 emplace(initializer_list<_Up> __il, _Args&&... __args) 00688 { 00689 this->_M_reset(); 00690 this->_M_construct(__il, std::forward<_Args>(__args)...); 00691 } 00692 00693 // [X.Y.4.2] Destructor is implicit, implemented in _Optional_base. 00694 00695 // [X.Y.4.4] Swap. 00696 void 00697 swap(optional& __other) 00698 noexcept(is_nothrow_move_constructible<_Tp>() 00699 && noexcept(swap(declval<_Tp&>(), declval<_Tp&>()))) 00700 { 00701 using std::swap; 00702 00703 if (this->_M_is_engaged() && __other._M_is_engaged()) 00704 swap(this->_M_get(), __other._M_get()); 00705 else if (this->_M_is_engaged()) 00706 { 00707 __other._M_construct(std::move(this->_M_get())); 00708 this->_M_destruct(); 00709 } 00710 else if (__other._M_is_engaged()) 00711 { 00712 this->_M_construct(std::move(__other._M_get())); 00713 __other._M_destruct(); 00714 } 00715 } 00716 00717 // [X.Y.4.5] Observers. 00718 constexpr const _Tp* 00719 operator->() const 00720 { return __constexpr_addressof(this->_M_get()); } 00721 00722 _Tp* 00723 operator->() 00724 { return std::__addressof(this->_M_get()); } 00725 00726 constexpr const _Tp& 00727 operator*() const& 00728 { return this->_M_get(); } 00729 00730 constexpr _Tp& 00731 operator*()& 00732 { return this->_M_get(); } 00733 00734 constexpr _Tp&& 00735 operator*()&& 00736 { return std::move(this->_M_get()); } 00737 00738 constexpr const _Tp&& 00739 operator*() const&& 00740 { return std::move(this->_M_get()); } 00741 00742 constexpr explicit operator bool() const noexcept 00743 { return this->_M_is_engaged(); } 00744 00745 constexpr const _Tp& 00746 value() const& 00747 { 00748 return this->_M_is_engaged() 00749 ? this->_M_get() 00750 : (__throw_bad_optional_access("Attempt to access value of a " 00751 "disengaged optional object"), 00752 this->_M_get()); 00753 } 00754 00755 constexpr _Tp& 00756 value()& 00757 { 00758 return this->_M_is_engaged() 00759 ? this->_M_get() 00760 : (__throw_bad_optional_access("Attempt to access value of a " 00761 "disengaged optional object"), 00762 this->_M_get()); 00763 } 00764 00765 constexpr _Tp&& 00766 value()&& 00767 { 00768 return this->_M_is_engaged() 00769 ? std::move(this->_M_get()) 00770 : (__throw_bad_optional_access("Attempt to access value of a " 00771 "disengaged optional object"), 00772 std::move(this->_M_get())); 00773 } 00774 00775 constexpr const _Tp&& 00776 value() const&& 00777 { 00778 return this->_M_is_engaged() 00779 ? std::move(this->_M_get()) 00780 : (__throw_bad_optional_access("Attempt to access value of a " 00781 "disengaged optional object"), 00782 std::move(this->_M_get())); 00783 } 00784 00785 template<typename _Up> 00786 constexpr _Tp 00787 value_or(_Up&& __u) const& 00788 { 00789 static_assert(__and_<is_copy_constructible<_Tp>, 00790 is_convertible<_Up&&, _Tp>>(), 00791 "Cannot return value"); 00792 00793 return this->_M_is_engaged() 00794 ? this->_M_get() 00795 : static_cast<_Tp>(std::forward<_Up>(__u)); 00796 } 00797 00798 template<typename _Up> 00799 _Tp 00800 value_or(_Up&& __u) && 00801 { 00802 static_assert(__and_<is_move_constructible<_Tp>, 00803 is_convertible<_Up&&, _Tp>>(), 00804 "Cannot return value" ); 00805 00806 return this->_M_is_engaged() 00807 ? std::move(this->_M_get()) 00808 : static_cast<_Tp>(std::forward<_Up>(__u)); 00809 } 00810 }; 00811 00812 // [X.Y.8] Comparisons between optional values. 00813 template<typename _Tp> 00814 constexpr bool 00815 operator==(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 00816 { 00817 return static_cast<bool>(__lhs) == static_cast<bool>(__rhs) 00818 && (!__lhs || *__lhs == *__rhs); 00819 } 00820 00821 template<typename _Tp> 00822 constexpr bool 00823 operator!=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 00824 { return !(__lhs == __rhs); } 00825 00826 template<typename _Tp> 00827 constexpr bool 00828 operator<(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 00829 { 00830 return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs); 00831 } 00832 00833 template<typename _Tp> 00834 constexpr bool 00835 operator>(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 00836 { return __rhs < __lhs; } 00837 00838 template<typename _Tp> 00839 constexpr bool 00840 operator<=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 00841 { return !(__rhs < __lhs); } 00842 00843 template<typename _Tp> 00844 constexpr bool 00845 operator>=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 00846 { return !(__lhs < __rhs); } 00847 00848 // [X.Y.9] Comparisons with nullopt. 00849 template<typename _Tp> 00850 constexpr bool 00851 operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept 00852 { return !__lhs; } 00853 00854 template<typename _Tp> 00855 constexpr bool 00856 operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept 00857 { return !__rhs; } 00858 00859 template<typename _Tp> 00860 constexpr bool 00861 operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept 00862 { return static_cast<bool>(__lhs); } 00863 00864 template<typename _Tp> 00865 constexpr bool 00866 operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept 00867 { return static_cast<bool>(__rhs); } 00868 00869 template<typename _Tp> 00870 constexpr bool 00871 operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept 00872 { return false; } 00873 00874 template<typename _Tp> 00875 constexpr bool 00876 operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept 00877 { return static_cast<bool>(__rhs); } 00878 00879 template<typename _Tp> 00880 constexpr bool 00881 operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept 00882 { return static_cast<bool>(__lhs); } 00883 00884 template<typename _Tp> 00885 constexpr bool 00886 operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept 00887 { return false; } 00888 00889 template<typename _Tp> 00890 constexpr bool 00891 operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept 00892 { return !__lhs; } 00893 00894 template<typename _Tp> 00895 constexpr bool 00896 operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept 00897 { return true; } 00898 00899 template<typename _Tp> 00900 constexpr bool 00901 operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept 00902 { return true; } 00903 00904 template<typename _Tp> 00905 constexpr bool 00906 operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept 00907 { return !__rhs; } 00908 00909 // [X.Y.10] Comparisons with value type. 00910 template<typename _Tp> 00911 constexpr bool 00912 operator==(const optional<_Tp>& __lhs, const _Tp& __rhs) 00913 { return __lhs && *__lhs == __rhs; } 00914 00915 template<typename _Tp> 00916 constexpr bool 00917 operator==(const _Tp& __lhs, const optional<_Tp>& __rhs) 00918 { return __rhs && __lhs == *__rhs; } 00919 00920 template<typename _Tp> 00921 constexpr bool 00922 operator!=(const optional<_Tp>& __lhs, _Tp const& __rhs) 00923 { return !__lhs || !(*__lhs == __rhs); } 00924 00925 template<typename _Tp> 00926 constexpr bool 00927 operator!=(const _Tp& __lhs, const optional<_Tp>& __rhs) 00928 { return !__rhs || !(__lhs == *__rhs); } 00929 00930 template<typename _Tp> 00931 constexpr bool 00932 operator<(const optional<_Tp>& __lhs, const _Tp& __rhs) 00933 { return !__lhs || *__lhs < __rhs; } 00934 00935 template<typename _Tp> 00936 constexpr bool 00937 operator<(const _Tp& __lhs, const optional<_Tp>& __rhs) 00938 { return __rhs && __lhs < *__rhs; } 00939 00940 template<typename _Tp> 00941 constexpr bool 00942 operator>(const optional<_Tp>& __lhs, const _Tp& __rhs) 00943 { return __lhs && __rhs < *__lhs; } 00944 00945 template<typename _Tp> 00946 constexpr bool 00947 operator>(const _Tp& __lhs, const optional<_Tp>& __rhs) 00948 { return !__rhs || *__rhs < __lhs; } 00949 00950 template<typename _Tp> 00951 constexpr bool 00952 operator<=(const optional<_Tp>& __lhs, const _Tp& __rhs) 00953 { return !__lhs || !(__rhs < *__lhs); } 00954 00955 template<typename _Tp> 00956 constexpr bool 00957 operator<=(const _Tp& __lhs, const optional<_Tp>& __rhs) 00958 { return __rhs && !(*__rhs < __lhs); } 00959 00960 template<typename _Tp> 00961 constexpr bool 00962 operator>=(const optional<_Tp>& __lhs, const _Tp& __rhs) 00963 { return __lhs && !(*__lhs < __rhs); } 00964 00965 template<typename _Tp> 00966 constexpr bool 00967 operator>=(const _Tp& __lhs, const optional<_Tp>& __rhs) 00968 { return !__rhs || !(__lhs < *__rhs); } 00969 00970 // [X.Y.11] 00971 template<typename _Tp> 00972 inline void 00973 swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs) 00974 noexcept(noexcept(__lhs.swap(__rhs))) 00975 { __lhs.swap(__rhs); } 00976 00977 template<typename _Tp> 00978 constexpr optional<decay_t<_Tp>> 00979 make_optional(_Tp&& __t) 00980 { return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; } 00981 00982 // @} group optional 00983 _GLIBCXX_END_NAMESPACE_VERSION 00984 } // namespace fundamentals_v1 00985 } 00986 00987 // [X.Y.12] 00988 template<typename _Tp> 00989 struct hash<experimental::optional<_Tp>> 00990 { 00991 using result_type = size_t; 00992 using argument_type = experimental::optional<_Tp>; 00993 00994 size_t 00995 operator()(const experimental::optional<_Tp>& __t) const 00996 noexcept(noexcept(hash<_Tp> {}(*__t))) 00997 { 00998 // We pick an arbitrary hash for disengaged optionals which hopefully 00999 // usual values of _Tp won't typically hash to. 01000 constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333); 01001 return __t ? hash<_Tp> {}(*__t) : __magic_disengaged_hash; 01002 } 01003 }; 01004 } 01005 01006 #endif // C++14 01007 01008 #endif // _GLIBCXX_EXPERIMENTAL_OPTIONAL