1 1.7 mrg // <experimental/optional> -*- C++ -*- 2 1.1 mrg 3 1.8 mrg // Copyright (C) 2013-2022 Free Software Foundation, Inc. 4 1.1 mrg // 5 1.1 mrg // This file is part of the GNU ISO C++ Library. This library is free 6 1.1 mrg // software; you can redistribute it and/or modify it under the 7 1.1 mrg // terms of the GNU General Public License as published by the 8 1.1 mrg // Free Software Foundation; either version 3, or (at your option) 9 1.1 mrg // any later version. 10 1.1 mrg 11 1.1 mrg // This library is distributed in the hope that it will be useful, 12 1.1 mrg // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1 mrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 1.1 mrg // GNU General Public License for more details. 15 1.1 mrg 16 1.1 mrg // Under Section 7 of GPL version 3, you are granted additional 17 1.1 mrg // permissions described in the GCC Runtime Library Exception, version 18 1.1 mrg // 3.1, as published by the Free Software Foundation. 19 1.1 mrg 20 1.1 mrg // You should have received a copy of the GNU General Public License and 21 1.1 mrg // a copy of the GCC Runtime Library Exception along with this program; 22 1.1 mrg // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 1.1 mrg // <http://www.gnu.org/licenses/>. 24 1.1 mrg 25 1.1 mrg /** @file experimental/optional 26 1.1 mrg * This is a TS C++ Library header. 27 1.6 mrg * @ingroup libfund-ts 28 1.1 mrg */ 29 1.1 mrg 30 1.1 mrg #ifndef _GLIBCXX_EXPERIMENTAL_OPTIONAL 31 1.1 mrg #define _GLIBCXX_EXPERIMENTAL_OPTIONAL 1 32 1.1 mrg 33 1.3 mrg #if __cplusplus >= 201402L 34 1.1 mrg 35 1.1 mrg #include <type_traits> 36 1.1 mrg #include <stdexcept> 37 1.1 mrg #include <new> 38 1.1 mrg #include <initializer_list> 39 1.1 mrg #include <bits/functexcept.h> 40 1.1 mrg #include <bits/functional_hash.h> 41 1.1 mrg #include <bits/enable_special_members.h> 42 1.8 mrg #include <bits/move.h> 43 1.3 mrg #include <experimental/bits/lfts_config.h> 44 1.1 mrg 45 1.1 mrg namespace std _GLIBCXX_VISIBILITY(default) 46 1.1 mrg { 47 1.4 mrg _GLIBCXX_BEGIN_NAMESPACE_VERSION 48 1.4 mrg 49 1.1 mrg namespace experimental 50 1.1 mrg { 51 1.1 mrg inline namespace fundamentals_v1 52 1.1 mrg { 53 1.1 mrg /** 54 1.1 mrg * @defgroup optional Optional values 55 1.6 mrg * @ingroup libfund-ts 56 1.1 mrg * 57 1.1 mrg * Class template for optional values and surrounding facilities, as 58 1.1 mrg * described in n3793 "A proposal to add a utility class to represent 59 1.1 mrg * optional objects (Revision 5)". 60 1.1 mrg * 61 1.1 mrg * @{ 62 1.1 mrg */ 63 1.1 mrg 64 1.1 mrg #define __cpp_lib_experimental_optional 201411 65 1.1 mrg 66 1.1 mrg // All subsequent [X.Y.n] references are against n3793. 67 1.1 mrg 68 1.1 mrg // [X.Y.4] 69 1.1 mrg template<typename _Tp> 70 1.1 mrg class optional; 71 1.1 mrg 72 1.1 mrg // [X.Y.5] 73 1.1 mrg /// Tag type for in-place construction. 74 1.1 mrg struct in_place_t { }; 75 1.1 mrg 76 1.1 mrg /// Tag for in-place construction. 77 1.1 mrg constexpr in_place_t in_place { }; 78 1.1 mrg 79 1.1 mrg // [X.Y.6] 80 1.1 mrg /// Tag type to disengage optional objects. 81 1.1 mrg struct nullopt_t 82 1.1 mrg { 83 1.1 mrg // Do not user-declare default constructor at all for 84 1.1 mrg // optional_value = {} syntax to work. 85 1.1 mrg // nullopt_t() = delete; 86 1.1 mrg 87 1.1 mrg // Used for constructing nullopt. 88 1.1 mrg enum class _Construct { _Token }; 89 1.1 mrg 90 1.1 mrg // Must be constexpr for nullopt_t to be literal. 91 1.1 mrg explicit constexpr nullopt_t(_Construct) { } 92 1.1 mrg }; 93 1.1 mrg 94 1.1 mrg // [X.Y.6] 95 1.1 mrg /// Tag to disengage optional objects. 96 1.1 mrg constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token }; 97 1.1 mrg 98 1.1 mrg // [X.Y.7] 99 1.1 mrg /** 100 1.1 mrg * @brief Exception class thrown when a disengaged optional object is 101 1.1 mrg * dereferenced. 102 1.1 mrg * @ingroup exceptions 103 1.1 mrg */ 104 1.1 mrg class bad_optional_access : public logic_error 105 1.1 mrg { 106 1.1 mrg public: 107 1.1 mrg bad_optional_access() : logic_error("bad optional access") { } 108 1.1 mrg 109 1.1 mrg // XXX This constructor is non-standard. Should not be inline 110 1.1 mrg explicit bad_optional_access(const char* __arg) : logic_error(__arg) { } 111 1.1 mrg 112 1.1 mrg virtual ~bad_optional_access() noexcept = default; 113 1.1 mrg }; 114 1.1 mrg 115 1.6 mrg /// @cond undocumented 116 1.6 mrg 117 1.1 mrg // XXX Does not belong here. 118 1.8 mrg [[noreturn]] inline void 119 1.1 mrg __throw_bad_optional_access(const char* __s) 120 1.1 mrg { _GLIBCXX_THROW_OR_ABORT(bad_optional_access(__s)); } 121 1.1 mrg 122 1.1 mrg /** 123 1.1 mrg * @brief Class template that holds the necessary state for @ref optional 124 1.1 mrg * and that has the responsibility for construction and the special members. 125 1.1 mrg * 126 1.1 mrg * Such a separate base class template is necessary in order to 127 1.1 mrg * conditionally enable the special members (e.g. copy/move constructors). 128 1.1 mrg * Note that this means that @ref _Optional_base implements the 129 1.1 mrg * functionality for copy and move assignment, but not for converting 130 1.1 mrg * assignment. 131 1.1 mrg * 132 1.1 mrg * @see optional, _Enable_special_members 133 1.1 mrg */ 134 1.1 mrg template<typename _Tp, bool _ShouldProvideDestructor = 135 1.1 mrg !is_trivially_destructible<_Tp>::value> 136 1.1 mrg class _Optional_base 137 1.1 mrg { 138 1.1 mrg private: 139 1.1 mrg // Remove const to avoid prohibition of reusing object storage for 140 1.1 mrg // const-qualified types in [3.8/9]. This is strictly internal 141 1.1 mrg // and even optional itself is oblivious to it. 142 1.1 mrg using _Stored_type = remove_const_t<_Tp>; 143 1.1 mrg 144 1.1 mrg public: 145 1.1 mrg // [X.Y.4.1] Constructors. 146 1.1 mrg 147 1.1 mrg // Constructors for disengaged optionals. 148 1.1 mrg constexpr _Optional_base() noexcept 149 1.1 mrg : _M_empty{} { } 150 1.1 mrg 151 1.1 mrg constexpr _Optional_base(nullopt_t) noexcept 152 1.1 mrg : _Optional_base{} { } 153 1.1 mrg 154 1.1 mrg // Constructors for engaged optionals. 155 1.1 mrg template<typename... _Args> 156 1.1 mrg constexpr explicit _Optional_base(in_place_t, _Args&&... __args) 157 1.1 mrg : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { } 158 1.1 mrg 159 1.1 mrg template<typename _Up, typename... _Args, 160 1.1 mrg enable_if_t<is_constructible<_Tp, 161 1.1 mrg initializer_list<_Up>&, 162 1.1 mrg _Args&&...>::value, 163 1.1 mrg int>...> 164 1.1 mrg constexpr explicit _Optional_base(in_place_t, 165 1.1 mrg initializer_list<_Up> __il, 166 1.1 mrg _Args&&... __args) 167 1.1 mrg : _M_payload(__il, std::forward<_Args>(__args)...), 168 1.1 mrg _M_engaged(true) { } 169 1.1 mrg 170 1.1 mrg // Copy and move constructors. 171 1.1 mrg _Optional_base(const _Optional_base& __other) 172 1.1 mrg { 173 1.1 mrg if (__other._M_engaged) 174 1.1 mrg this->_M_construct(__other._M_get()); 175 1.1 mrg } 176 1.1 mrg 177 1.1 mrg _Optional_base(_Optional_base&& __other) 178 1.1 mrg noexcept(is_nothrow_move_constructible<_Tp>()) 179 1.1 mrg { 180 1.1 mrg if (__other._M_engaged) 181 1.1 mrg this->_M_construct(std::move(__other._M_get())); 182 1.1 mrg } 183 1.1 mrg 184 1.1 mrg // [X.Y.4.3] (partly) Assignment. 185 1.1 mrg _Optional_base& 186 1.1 mrg operator=(const _Optional_base& __other) 187 1.1 mrg { 188 1.1 mrg if (this->_M_engaged && __other._M_engaged) 189 1.1 mrg this->_M_get() = __other._M_get(); 190 1.1 mrg else 191 1.1 mrg { 192 1.1 mrg if (__other._M_engaged) 193 1.1 mrg this->_M_construct(__other._M_get()); 194 1.1 mrg else 195 1.1 mrg this->_M_reset(); 196 1.1 mrg } 197 1.1 mrg 198 1.1 mrg return *this; 199 1.1 mrg } 200 1.1 mrg 201 1.1 mrg _Optional_base& 202 1.1 mrg operator=(_Optional_base&& __other) 203 1.1 mrg noexcept(__and_<is_nothrow_move_constructible<_Tp>, 204 1.1 mrg is_nothrow_move_assignable<_Tp>>()) 205 1.1 mrg { 206 1.1 mrg if (this->_M_engaged && __other._M_engaged) 207 1.1 mrg this->_M_get() = std::move(__other._M_get()); 208 1.1 mrg else 209 1.1 mrg { 210 1.1 mrg if (__other._M_engaged) 211 1.1 mrg this->_M_construct(std::move(__other._M_get())); 212 1.1 mrg else 213 1.1 mrg this->_M_reset(); 214 1.1 mrg } 215 1.1 mrg return *this; 216 1.1 mrg } 217 1.1 mrg 218 1.1 mrg // [X.Y.4.2] Destructor. 219 1.1 mrg ~_Optional_base() 220 1.1 mrg { 221 1.1 mrg if (this->_M_engaged) 222 1.1 mrg this->_M_payload.~_Stored_type(); 223 1.1 mrg } 224 1.1 mrg 225 1.1 mrg // The following functionality is also needed by optional, hence the 226 1.1 mrg // protected accessibility. 227 1.1 mrg protected: 228 1.1 mrg constexpr bool _M_is_engaged() const noexcept 229 1.1 mrg { return this->_M_engaged; } 230 1.1 mrg 231 1.1 mrg // The _M_get operations have _M_engaged as a precondition. 232 1.1 mrg constexpr _Tp& 233 1.1 mrg _M_get() noexcept 234 1.1 mrg { return _M_payload; } 235 1.1 mrg 236 1.1 mrg constexpr const _Tp& 237 1.1 mrg _M_get() const noexcept 238 1.1 mrg { return _M_payload; } 239 1.1 mrg 240 1.1 mrg // The _M_construct operation has !_M_engaged as a precondition 241 1.1 mrg // while _M_destruct has _M_engaged as a precondition. 242 1.1 mrg template<typename... _Args> 243 1.1 mrg void 244 1.1 mrg _M_construct(_Args&&... __args) 245 1.1 mrg noexcept(is_nothrow_constructible<_Stored_type, _Args...>()) 246 1.1 mrg { 247 1.1 mrg ::new (std::__addressof(this->_M_payload)) 248 1.1 mrg _Stored_type(std::forward<_Args>(__args)...); 249 1.1 mrg this->_M_engaged = true; 250 1.1 mrg } 251 1.1 mrg 252 1.1 mrg void 253 1.1 mrg _M_destruct() 254 1.1 mrg { 255 1.1 mrg this->_M_engaged = false; 256 1.1 mrg this->_M_payload.~_Stored_type(); 257 1.1 mrg } 258 1.1 mrg 259 1.1 mrg // _M_reset is a 'safe' operation with no precondition. 260 1.1 mrg void 261 1.1 mrg _M_reset() 262 1.1 mrg { 263 1.1 mrg if (this->_M_engaged) 264 1.1 mrg this->_M_destruct(); 265 1.1 mrg } 266 1.1 mrg 267 1.1 mrg private: 268 1.1 mrg struct _Empty_byte { }; 269 1.1 mrg union { 270 1.1 mrg _Empty_byte _M_empty; 271 1.1 mrg _Stored_type _M_payload; 272 1.1 mrg }; 273 1.1 mrg bool _M_engaged = false; 274 1.1 mrg }; 275 1.1 mrg 276 1.1 mrg /// Partial specialization that is exactly identical to the primary template 277 1.1 mrg /// save for not providing a destructor, to fulfill triviality requirements. 278 1.1 mrg template<typename _Tp> 279 1.1 mrg class _Optional_base<_Tp, false> 280 1.1 mrg { 281 1.1 mrg private: 282 1.1 mrg using _Stored_type = remove_const_t<_Tp>; 283 1.1 mrg 284 1.1 mrg public: 285 1.1 mrg constexpr _Optional_base() noexcept 286 1.1 mrg : _M_empty{} { } 287 1.1 mrg 288 1.1 mrg constexpr _Optional_base(nullopt_t) noexcept 289 1.1 mrg : _Optional_base{} { } 290 1.1 mrg 291 1.1 mrg template<typename... _Args> 292 1.1 mrg constexpr explicit _Optional_base(in_place_t, _Args&&... __args) 293 1.1 mrg : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { } 294 1.1 mrg 295 1.1 mrg template<typename _Up, typename... _Args, 296 1.1 mrg enable_if_t<is_constructible<_Tp, 297 1.1 mrg initializer_list<_Up>&, 298 1.1 mrg _Args&&...>::value, 299 1.1 mrg int>...> 300 1.1 mrg constexpr explicit _Optional_base(in_place_t, 301 1.1 mrg initializer_list<_Up> __il, 302 1.1 mrg _Args&&... __args) 303 1.1 mrg : _M_payload(__il, std::forward<_Args>(__args)...), 304 1.1 mrg _M_engaged(true) { } 305 1.1 mrg 306 1.1 mrg _Optional_base(const _Optional_base& __other) 307 1.1 mrg { 308 1.1 mrg if (__other._M_engaged) 309 1.1 mrg this->_M_construct(__other._M_get()); 310 1.1 mrg } 311 1.1 mrg 312 1.1 mrg _Optional_base(_Optional_base&& __other) 313 1.1 mrg noexcept(is_nothrow_move_constructible<_Tp>()) 314 1.1 mrg { 315 1.1 mrg if (__other._M_engaged) 316 1.1 mrg this->_M_construct(std::move(__other._M_get())); 317 1.1 mrg } 318 1.1 mrg 319 1.1 mrg _Optional_base& 320 1.1 mrg operator=(const _Optional_base& __other) 321 1.1 mrg { 322 1.1 mrg if (this->_M_engaged && __other._M_engaged) 323 1.1 mrg this->_M_get() = __other._M_get(); 324 1.1 mrg else 325 1.1 mrg { 326 1.1 mrg if (__other._M_engaged) 327 1.1 mrg this->_M_construct(__other._M_get()); 328 1.1 mrg else 329 1.1 mrg this->_M_reset(); 330 1.1 mrg } 331 1.1 mrg return *this; 332 1.1 mrg } 333 1.1 mrg 334 1.1 mrg _Optional_base& 335 1.1 mrg operator=(_Optional_base&& __other) 336 1.1 mrg noexcept(__and_<is_nothrow_move_constructible<_Tp>, 337 1.1 mrg is_nothrow_move_assignable<_Tp>>()) 338 1.1 mrg { 339 1.1 mrg if (this->_M_engaged && __other._M_engaged) 340 1.1 mrg this->_M_get() = std::move(__other._M_get()); 341 1.1 mrg else 342 1.1 mrg { 343 1.1 mrg if (__other._M_engaged) 344 1.1 mrg this->_M_construct(std::move(__other._M_get())); 345 1.1 mrg else 346 1.1 mrg this->_M_reset(); 347 1.1 mrg } 348 1.1 mrg return *this; 349 1.1 mrg } 350 1.1 mrg 351 1.1 mrg // Sole difference 352 1.1 mrg // ~_Optional_base() noexcept = default; 353 1.1 mrg 354 1.1 mrg protected: 355 1.1 mrg constexpr bool _M_is_engaged() const noexcept 356 1.1 mrg { return this->_M_engaged; } 357 1.1 mrg 358 1.1 mrg _Tp& 359 1.1 mrg _M_get() noexcept 360 1.1 mrg { return _M_payload; } 361 1.1 mrg 362 1.1 mrg constexpr const _Tp& 363 1.1 mrg _M_get() const noexcept 364 1.1 mrg { return _M_payload; } 365 1.1 mrg 366 1.1 mrg template<typename... _Args> 367 1.1 mrg void 368 1.1 mrg _M_construct(_Args&&... __args) 369 1.1 mrg noexcept(is_nothrow_constructible<_Stored_type, _Args...>()) 370 1.1 mrg { 371 1.1 mrg ::new (std::__addressof(this->_M_payload)) 372 1.1 mrg _Stored_type(std::forward<_Args>(__args)...); 373 1.1 mrg this->_M_engaged = true; 374 1.1 mrg } 375 1.1 mrg 376 1.1 mrg void 377 1.1 mrg _M_destruct() 378 1.1 mrg { 379 1.1 mrg this->_M_engaged = false; 380 1.1 mrg this->_M_payload.~_Stored_type(); 381 1.1 mrg } 382 1.1 mrg 383 1.1 mrg void 384 1.1 mrg _M_reset() 385 1.1 mrg { 386 1.1 mrg if (this->_M_engaged) 387 1.1 mrg this->_M_destruct(); 388 1.1 mrg } 389 1.1 mrg 390 1.1 mrg private: 391 1.1 mrg struct _Empty_byte { }; 392 1.1 mrg union 393 1.1 mrg { 394 1.1 mrg _Empty_byte _M_empty; 395 1.1 mrg _Stored_type _M_payload; 396 1.1 mrg }; 397 1.1 mrg bool _M_engaged = false; 398 1.1 mrg }; 399 1.1 mrg 400 1.3 mrg template<typename _Tp, typename _Up> 401 1.3 mrg using __converts_from_optional = 402 1.3 mrg __or_<is_constructible<_Tp, const optional<_Up>&>, 403 1.3 mrg is_constructible<_Tp, optional<_Up>&>, 404 1.3 mrg is_constructible<_Tp, const optional<_Up>&&>, 405 1.3 mrg is_constructible<_Tp, optional<_Up>&&>, 406 1.3 mrg is_convertible<const optional<_Up>&, _Tp>, 407 1.3 mrg is_convertible<optional<_Up>&, _Tp>, 408 1.3 mrg is_convertible<const optional<_Up>&&, _Tp>, 409 1.3 mrg is_convertible<optional<_Up>&&, _Tp>>; 410 1.3 mrg 411 1.3 mrg template<typename _Tp, typename _Up> 412 1.3 mrg using __assigns_from_optional = 413 1.3 mrg __or_<is_assignable<_Tp&, const optional<_Up>&>, 414 1.3 mrg is_assignable<_Tp&, optional<_Up>&>, 415 1.3 mrg is_assignable<_Tp&, const optional<_Up>&&>, 416 1.3 mrg is_assignable<_Tp&, optional<_Up>&&>>; 417 1.3 mrg 418 1.6 mrg /// @endcond 419 1.6 mrg 420 1.1 mrg /** 421 1.1 mrg * @brief Class template for optional values. 422 1.1 mrg */ 423 1.1 mrg template<typename _Tp> 424 1.1 mrg class optional 425 1.1 mrg : private _Optional_base<_Tp>, 426 1.1 mrg private _Enable_copy_move< 427 1.1 mrg // Copy constructor. 428 1.1 mrg is_copy_constructible<_Tp>::value, 429 1.1 mrg // Copy assignment. 430 1.1 mrg __and_<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>::value, 431 1.1 mrg // Move constructor. 432 1.1 mrg is_move_constructible<_Tp>::value, 433 1.1 mrg // Move assignment. 434 1.1 mrg __and_<is_move_constructible<_Tp>, is_move_assignable<_Tp>>::value, 435 1.1 mrg // Unique tag type. 436 1.1 mrg optional<_Tp>> 437 1.1 mrg { 438 1.1 mrg static_assert(__and_<__not_<is_same<remove_cv_t<_Tp>, nullopt_t>>, 439 1.1 mrg __not_<is_same<remove_cv_t<_Tp>, in_place_t>>, 440 1.1 mrg __not_<is_reference<_Tp>>>(), 441 1.1 mrg "Invalid instantiation of optional<T>"); 442 1.1 mrg 443 1.1 mrg private: 444 1.1 mrg using _Base = _Optional_base<_Tp>; 445 1.1 mrg 446 1.1 mrg public: 447 1.1 mrg using value_type = _Tp; 448 1.1 mrg 449 1.1 mrg // _Optional_base has the responsibility for construction. 450 1.1 mrg using _Base::_Base; 451 1.1 mrg 452 1.3 mrg constexpr optional() = default; 453 1.3 mrg // Converting constructors for engaged optionals. 454 1.3 mrg template <typename _Up = _Tp, 455 1.3 mrg enable_if_t<__and_< 456 1.3 mrg __not_<is_same<optional<_Tp>, decay_t<_Up>>>, 457 1.3 mrg is_constructible<_Tp, _Up&&>, 458 1.3 mrg is_convertible<_Up&&, _Tp> 459 1.3 mrg >::value, bool> = true> 460 1.3 mrg constexpr optional(_Up&& __t) 461 1.3 mrg : _Base(in_place, std::forward<_Up>(__t)) { } 462 1.3 mrg 463 1.3 mrg template <typename _Up = _Tp, 464 1.3 mrg enable_if_t<__and_< 465 1.3 mrg __not_<is_same<optional<_Tp>, decay_t<_Up>>>, 466 1.3 mrg is_constructible<_Tp, _Up&&>, 467 1.3 mrg __not_<is_convertible<_Up&&, _Tp>> 468 1.3 mrg >::value, bool> = false> 469 1.3 mrg explicit constexpr optional(_Up&& __t) 470 1.3 mrg : _Base(in_place, std::forward<_Up>(__t)) { } 471 1.3 mrg 472 1.3 mrg template <typename _Up, 473 1.3 mrg enable_if_t<__and_< 474 1.3 mrg __not_<is_same<_Tp, _Up>>, 475 1.3 mrg is_constructible<_Tp, const _Up&>, 476 1.3 mrg is_convertible<const _Up&, _Tp>, 477 1.3 mrg __not_<__converts_from_optional<_Tp, _Up>> 478 1.3 mrg >::value, bool> = true> 479 1.3 mrg constexpr optional(const optional<_Up>& __t) 480 1.3 mrg { 481 1.3 mrg if (__t) 482 1.3 mrg emplace(*__t); 483 1.3 mrg } 484 1.3 mrg 485 1.3 mrg template <typename _Up, 486 1.3 mrg enable_if_t<__and_< 487 1.3 mrg __not_<is_same<_Tp, _Up>>, 488 1.3 mrg is_constructible<_Tp, const _Up&>, 489 1.3 mrg __not_<is_convertible<const _Up&, _Tp>>, 490 1.3 mrg __not_<__converts_from_optional<_Tp, _Up>> 491 1.3 mrg >::value, bool> = false> 492 1.3 mrg explicit constexpr optional(const optional<_Up>& __t) 493 1.3 mrg { 494 1.3 mrg if (__t) 495 1.3 mrg emplace(*__t); 496 1.3 mrg } 497 1.3 mrg 498 1.3 mrg template <typename _Up, 499 1.3 mrg enable_if_t<__and_< 500 1.3 mrg __not_<is_same<_Tp, _Up>>, 501 1.3 mrg is_constructible<_Tp, _Up&&>, 502 1.3 mrg is_convertible<_Up&&, _Tp>, 503 1.3 mrg __not_<__converts_from_optional<_Tp, _Up>> 504 1.3 mrg >::value, bool> = true> 505 1.3 mrg constexpr optional(optional<_Up>&& __t) 506 1.3 mrg { 507 1.3 mrg if (__t) 508 1.3 mrg emplace(std::move(*__t)); 509 1.3 mrg } 510 1.3 mrg 511 1.3 mrg template <typename _Up, 512 1.3 mrg enable_if_t<__and_< 513 1.3 mrg __not_<is_same<_Tp, _Up>>, 514 1.3 mrg is_constructible<_Tp, _Up&&>, 515 1.3 mrg __not_<is_convertible<_Up&&, _Tp>>, 516 1.3 mrg __not_<__converts_from_optional<_Tp, _Up>> 517 1.3 mrg >::value, bool> = false> 518 1.3 mrg explicit constexpr optional(optional<_Up>&& __t) 519 1.3 mrg { 520 1.3 mrg if (__t) 521 1.3 mrg emplace(std::move(*__t)); 522 1.3 mrg } 523 1.3 mrg 524 1.1 mrg // [X.Y.4.3] (partly) Assignment. 525 1.1 mrg optional& 526 1.1 mrg operator=(nullopt_t) noexcept 527 1.1 mrg { 528 1.1 mrg this->_M_reset(); 529 1.1 mrg return *this; 530 1.1 mrg } 531 1.1 mrg 532 1.3 mrg template<typename _Up = _Tp> 533 1.3 mrg enable_if_t<__and_< 534 1.3 mrg __not_<is_same<optional<_Tp>, decay_t<_Up>>>, 535 1.3 mrg is_constructible<_Tp, _Up>, 536 1.3 mrg __not_<__and_<is_scalar<_Tp>, 537 1.3 mrg is_same<_Tp, decay_t<_Up>>>>, 538 1.3 mrg is_assignable<_Tp&, _Up>>::value, 539 1.3 mrg optional&> 540 1.1 mrg operator=(_Up&& __u) 541 1.1 mrg { 542 1.1 mrg if (this->_M_is_engaged()) 543 1.1 mrg this->_M_get() = std::forward<_Up>(__u); 544 1.1 mrg else 545 1.1 mrg this->_M_construct(std::forward<_Up>(__u)); 546 1.1 mrg 547 1.1 mrg return *this; 548 1.1 mrg } 549 1.1 mrg 550 1.3 mrg template<typename _Up> 551 1.3 mrg enable_if_t<__and_< 552 1.3 mrg __not_<is_same<_Tp, _Up>>, 553 1.3 mrg is_constructible<_Tp, const _Up&>, 554 1.3 mrg is_assignable<_Tp&, _Up>, 555 1.3 mrg __not_<__converts_from_optional<_Tp, _Up>>, 556 1.3 mrg __not_<__assigns_from_optional<_Tp, _Up>> 557 1.3 mrg >::value, 558 1.3 mrg optional&> 559 1.3 mrg operator=(const optional<_Up>& __u) 560 1.3 mrg { 561 1.3 mrg if (__u) 562 1.3 mrg { 563 1.3 mrg if (this->_M_is_engaged()) 564 1.3 mrg this->_M_get() = *__u; 565 1.3 mrg else 566 1.3 mrg this->_M_construct(*__u); 567 1.3 mrg } 568 1.3 mrg else 569 1.3 mrg { 570 1.3 mrg this->_M_reset(); 571 1.3 mrg } 572 1.3 mrg return *this; 573 1.3 mrg } 574 1.3 mrg 575 1.3 mrg template<typename _Up> 576 1.3 mrg enable_if_t<__and_< 577 1.3 mrg __not_<is_same<_Tp, _Up>>, 578 1.3 mrg is_constructible<_Tp, _Up>, 579 1.3 mrg is_assignable<_Tp&, _Up>, 580 1.3 mrg __not_<__converts_from_optional<_Tp, _Up>>, 581 1.3 mrg __not_<__assigns_from_optional<_Tp, _Up>> 582 1.3 mrg >::value, 583 1.3 mrg optional&> 584 1.3 mrg operator=(optional<_Up>&& __u) 585 1.3 mrg { 586 1.3 mrg if (__u) 587 1.3 mrg { 588 1.3 mrg if (this->_M_is_engaged()) 589 1.3 mrg this->_M_get() = std::move(*__u); 590 1.3 mrg else 591 1.3 mrg this->_M_construct(std::move(*__u)); 592 1.3 mrg } 593 1.3 mrg else 594 1.3 mrg { 595 1.3 mrg this->_M_reset(); 596 1.3 mrg } 597 1.3 mrg 598 1.3 mrg return *this; 599 1.3 mrg } 600 1.3 mrg 601 1.1 mrg template<typename... _Args> 602 1.3 mrg enable_if_t<is_constructible<_Tp, _Args&&...>::value> 603 1.1 mrg emplace(_Args&&... __args) 604 1.1 mrg { 605 1.1 mrg this->_M_reset(); 606 1.1 mrg this->_M_construct(std::forward<_Args>(__args)...); 607 1.1 mrg } 608 1.1 mrg 609 1.1 mrg template<typename _Up, typename... _Args> 610 1.3 mrg enable_if_t<is_constructible<_Tp, initializer_list<_Up>&, 611 1.1 mrg _Args&&...>::value> 612 1.1 mrg emplace(initializer_list<_Up> __il, _Args&&... __args) 613 1.1 mrg { 614 1.1 mrg this->_M_reset(); 615 1.1 mrg this->_M_construct(__il, std::forward<_Args>(__args)...); 616 1.1 mrg } 617 1.1 mrg 618 1.1 mrg // [X.Y.4.2] Destructor is implicit, implemented in _Optional_base. 619 1.1 mrg 620 1.1 mrg // [X.Y.4.4] Swap. 621 1.1 mrg void 622 1.1 mrg swap(optional& __other) 623 1.1 mrg noexcept(is_nothrow_move_constructible<_Tp>() 624 1.4 mrg && __is_nothrow_swappable<_Tp>::value) 625 1.1 mrg { 626 1.1 mrg using std::swap; 627 1.1 mrg 628 1.1 mrg if (this->_M_is_engaged() && __other._M_is_engaged()) 629 1.1 mrg swap(this->_M_get(), __other._M_get()); 630 1.1 mrg else if (this->_M_is_engaged()) 631 1.1 mrg { 632 1.1 mrg __other._M_construct(std::move(this->_M_get())); 633 1.1 mrg this->_M_destruct(); 634 1.1 mrg } 635 1.1 mrg else if (__other._M_is_engaged()) 636 1.1 mrg { 637 1.1 mrg this->_M_construct(std::move(__other._M_get())); 638 1.1 mrg __other._M_destruct(); 639 1.1 mrg } 640 1.1 mrg } 641 1.1 mrg 642 1.1 mrg // [X.Y.4.5] Observers. 643 1.1 mrg constexpr const _Tp* 644 1.1 mrg operator->() const 645 1.6 mrg { return std::__addressof(this->_M_get()); } 646 1.1 mrg 647 1.1 mrg _Tp* 648 1.1 mrg operator->() 649 1.1 mrg { return std::__addressof(this->_M_get()); } 650 1.1 mrg 651 1.1 mrg constexpr const _Tp& 652 1.1 mrg operator*() const& 653 1.1 mrg { return this->_M_get(); } 654 1.1 mrg 655 1.1 mrg constexpr _Tp& 656 1.1 mrg operator*()& 657 1.1 mrg { return this->_M_get(); } 658 1.1 mrg 659 1.1 mrg constexpr _Tp&& 660 1.1 mrg operator*()&& 661 1.1 mrg { return std::move(this->_M_get()); } 662 1.1 mrg 663 1.1 mrg constexpr const _Tp&& 664 1.1 mrg operator*() const&& 665 1.1 mrg { return std::move(this->_M_get()); } 666 1.1 mrg 667 1.1 mrg constexpr explicit operator bool() const noexcept 668 1.1 mrg { return this->_M_is_engaged(); } 669 1.1 mrg 670 1.1 mrg constexpr const _Tp& 671 1.1 mrg value() const& 672 1.1 mrg { 673 1.8 mrg if (this->_M_is_engaged()) 674 1.8 mrg return this->_M_get(); 675 1.8 mrg __throw_bad_optional_access("Attempt to access value of a " 676 1.8 mrg "disengaged optional object"); 677 1.1 mrg } 678 1.1 mrg 679 1.1 mrg constexpr _Tp& 680 1.1 mrg value()& 681 1.1 mrg { 682 1.8 mrg if (this->_M_is_engaged()) 683 1.8 mrg return this->_M_get(); 684 1.8 mrg __throw_bad_optional_access("Attempt to access value of a " 685 1.8 mrg "disengaged optional object"); 686 1.1 mrg } 687 1.1 mrg 688 1.1 mrg constexpr _Tp&& 689 1.1 mrg value()&& 690 1.1 mrg { 691 1.8 mrg if (this->_M_is_engaged()) 692 1.8 mrg return std::move(this->_M_get()); 693 1.8 mrg __throw_bad_optional_access("Attempt to access value of a " 694 1.8 mrg "disengaged optional object"); 695 1.1 mrg } 696 1.1 mrg 697 1.1 mrg constexpr const _Tp&& 698 1.1 mrg value() const&& 699 1.1 mrg { 700 1.8 mrg if (this->_M_is_engaged()) 701 1.8 mrg return std::move(this->_M_get()); 702 1.8 mrg __throw_bad_optional_access("Attempt to access value of a " 703 1.8 mrg "disengaged optional object"); 704 1.1 mrg } 705 1.1 mrg 706 1.1 mrg template<typename _Up> 707 1.1 mrg constexpr _Tp 708 1.1 mrg value_or(_Up&& __u) const& 709 1.1 mrg { 710 1.1 mrg static_assert(__and_<is_copy_constructible<_Tp>, 711 1.1 mrg is_convertible<_Up&&, _Tp>>(), 712 1.1 mrg "Cannot return value"); 713 1.1 mrg 714 1.8 mrg if (this->_M_is_engaged()) 715 1.8 mrg return this->_M_get(); 716 1.8 mrg else 717 1.8 mrg return static_cast<_Tp>(std::forward<_Up>(__u)); 718 1.1 mrg } 719 1.1 mrg 720 1.1 mrg template<typename _Up> 721 1.1 mrg _Tp 722 1.1 mrg value_or(_Up&& __u) && 723 1.1 mrg { 724 1.1 mrg static_assert(__and_<is_move_constructible<_Tp>, 725 1.1 mrg is_convertible<_Up&&, _Tp>>(), 726 1.1 mrg "Cannot return value" ); 727 1.1 mrg 728 1.8 mrg if (this->_M_is_engaged()) 729 1.8 mrg return std::move(this->_M_get()); 730 1.8 mrg else 731 1.8 mrg return static_cast<_Tp>(std::forward<_Up>(__u)); 732 1.1 mrg } 733 1.1 mrg }; 734 1.1 mrg 735 1.6 mrg /// @relates experimental::optional @{ 736 1.6 mrg 737 1.1 mrg // [X.Y.8] Comparisons between optional values. 738 1.1 mrg template<typename _Tp> 739 1.1 mrg constexpr bool 740 1.1 mrg operator==(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 741 1.1 mrg { 742 1.1 mrg return static_cast<bool>(__lhs) == static_cast<bool>(__rhs) 743 1.1 mrg && (!__lhs || *__lhs == *__rhs); 744 1.1 mrg } 745 1.1 mrg 746 1.1 mrg template<typename _Tp> 747 1.1 mrg constexpr bool 748 1.1 mrg operator!=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 749 1.1 mrg { return !(__lhs == __rhs); } 750 1.1 mrg 751 1.1 mrg template<typename _Tp> 752 1.1 mrg constexpr bool 753 1.1 mrg operator<(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 754 1.1 mrg { 755 1.1 mrg return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs); 756 1.1 mrg } 757 1.1 mrg 758 1.1 mrg template<typename _Tp> 759 1.1 mrg constexpr bool 760 1.1 mrg operator>(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 761 1.1 mrg { return __rhs < __lhs; } 762 1.1 mrg 763 1.1 mrg template<typename _Tp> 764 1.1 mrg constexpr bool 765 1.1 mrg operator<=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 766 1.1 mrg { return !(__rhs < __lhs); } 767 1.1 mrg 768 1.1 mrg template<typename _Tp> 769 1.1 mrg constexpr bool 770 1.1 mrg operator>=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 771 1.1 mrg { return !(__lhs < __rhs); } 772 1.1 mrg 773 1.1 mrg // [X.Y.9] Comparisons with nullopt. 774 1.1 mrg template<typename _Tp> 775 1.1 mrg constexpr bool 776 1.1 mrg operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept 777 1.1 mrg { return !__lhs; } 778 1.1 mrg 779 1.1 mrg template<typename _Tp> 780 1.1 mrg constexpr bool 781 1.1 mrg operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept 782 1.1 mrg { return !__rhs; } 783 1.1 mrg 784 1.1 mrg template<typename _Tp> 785 1.1 mrg constexpr bool 786 1.1 mrg operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept 787 1.1 mrg { return static_cast<bool>(__lhs); } 788 1.1 mrg 789 1.1 mrg template<typename _Tp> 790 1.1 mrg constexpr bool 791 1.1 mrg operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept 792 1.1 mrg { return static_cast<bool>(__rhs); } 793 1.1 mrg 794 1.1 mrg template<typename _Tp> 795 1.1 mrg constexpr bool 796 1.1 mrg operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept 797 1.1 mrg { return false; } 798 1.1 mrg 799 1.1 mrg template<typename _Tp> 800 1.1 mrg constexpr bool 801 1.1 mrg operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept 802 1.1 mrg { return static_cast<bool>(__rhs); } 803 1.1 mrg 804 1.1 mrg template<typename _Tp> 805 1.1 mrg constexpr bool 806 1.1 mrg operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept 807 1.1 mrg { return static_cast<bool>(__lhs); } 808 1.1 mrg 809 1.1 mrg template<typename _Tp> 810 1.1 mrg constexpr bool 811 1.1 mrg operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept 812 1.1 mrg { return false; } 813 1.1 mrg 814 1.1 mrg template<typename _Tp> 815 1.1 mrg constexpr bool 816 1.1 mrg operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept 817 1.1 mrg { return !__lhs; } 818 1.1 mrg 819 1.1 mrg template<typename _Tp> 820 1.1 mrg constexpr bool 821 1.1 mrg operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept 822 1.1 mrg { return true; } 823 1.1 mrg 824 1.1 mrg template<typename _Tp> 825 1.1 mrg constexpr bool 826 1.1 mrg operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept 827 1.1 mrg { return true; } 828 1.1 mrg 829 1.1 mrg template<typename _Tp> 830 1.1 mrg constexpr bool 831 1.1 mrg operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept 832 1.1 mrg { return !__rhs; } 833 1.1 mrg 834 1.1 mrg // [X.Y.10] Comparisons with value type. 835 1.1 mrg template<typename _Tp> 836 1.1 mrg constexpr bool 837 1.1 mrg operator==(const optional<_Tp>& __lhs, const _Tp& __rhs) 838 1.1 mrg { return __lhs && *__lhs == __rhs; } 839 1.1 mrg 840 1.1 mrg template<typename _Tp> 841 1.1 mrg constexpr bool 842 1.1 mrg operator==(const _Tp& __lhs, const optional<_Tp>& __rhs) 843 1.1 mrg { return __rhs && __lhs == *__rhs; } 844 1.1 mrg 845 1.1 mrg template<typename _Tp> 846 1.1 mrg constexpr bool 847 1.1 mrg operator!=(const optional<_Tp>& __lhs, _Tp const& __rhs) 848 1.1 mrg { return !__lhs || !(*__lhs == __rhs); } 849 1.1 mrg 850 1.1 mrg template<typename _Tp> 851 1.1 mrg constexpr bool 852 1.1 mrg operator!=(const _Tp& __lhs, const optional<_Tp>& __rhs) 853 1.1 mrg { return !__rhs || !(__lhs == *__rhs); } 854 1.1 mrg 855 1.1 mrg template<typename _Tp> 856 1.1 mrg constexpr bool 857 1.1 mrg operator<(const optional<_Tp>& __lhs, const _Tp& __rhs) 858 1.1 mrg { return !__lhs || *__lhs < __rhs; } 859 1.1 mrg 860 1.1 mrg template<typename _Tp> 861 1.1 mrg constexpr bool 862 1.1 mrg operator<(const _Tp& __lhs, const optional<_Tp>& __rhs) 863 1.1 mrg { return __rhs && __lhs < *__rhs; } 864 1.1 mrg 865 1.1 mrg template<typename _Tp> 866 1.1 mrg constexpr bool 867 1.1 mrg operator>(const optional<_Tp>& __lhs, const _Tp& __rhs) 868 1.1 mrg { return __lhs && __rhs < *__lhs; } 869 1.1 mrg 870 1.1 mrg template<typename _Tp> 871 1.1 mrg constexpr bool 872 1.1 mrg operator>(const _Tp& __lhs, const optional<_Tp>& __rhs) 873 1.1 mrg { return !__rhs || *__rhs < __lhs; } 874 1.1 mrg 875 1.1 mrg template<typename _Tp> 876 1.1 mrg constexpr bool 877 1.1 mrg operator<=(const optional<_Tp>& __lhs, const _Tp& __rhs) 878 1.1 mrg { return !__lhs || !(__rhs < *__lhs); } 879 1.1 mrg 880 1.1 mrg template<typename _Tp> 881 1.1 mrg constexpr bool 882 1.1 mrg operator<=(const _Tp& __lhs, const optional<_Tp>& __rhs) 883 1.1 mrg { return __rhs && !(*__rhs < __lhs); } 884 1.1 mrg 885 1.1 mrg template<typename _Tp> 886 1.1 mrg constexpr bool 887 1.1 mrg operator>=(const optional<_Tp>& __lhs, const _Tp& __rhs) 888 1.1 mrg { return __lhs && !(*__lhs < __rhs); } 889 1.1 mrg 890 1.1 mrg template<typename _Tp> 891 1.1 mrg constexpr bool 892 1.1 mrg operator>=(const _Tp& __lhs, const optional<_Tp>& __rhs) 893 1.1 mrg { return !__rhs || !(__lhs < *__rhs); } 894 1.1 mrg 895 1.1 mrg // [X.Y.11] 896 1.1 mrg template<typename _Tp> 897 1.1 mrg inline void 898 1.1 mrg swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs) 899 1.1 mrg noexcept(noexcept(__lhs.swap(__rhs))) 900 1.1 mrg { __lhs.swap(__rhs); } 901 1.1 mrg 902 1.1 mrg template<typename _Tp> 903 1.1 mrg constexpr optional<decay_t<_Tp>> 904 1.1 mrg make_optional(_Tp&& __t) 905 1.1 mrg { return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; } 906 1.1 mrg 907 1.6 mrg /// @} relates experimental::optional 908 1.6 mrg /// @} group optional 909 1.1 mrg } // namespace fundamentals_v1 910 1.4 mrg } // namespace experimental 911 1.1 mrg 912 1.1 mrg // [X.Y.12] 913 1.6 mrg /// std::hash partial specialization for experimental::optional 914 1.6 mrg /// @relates experimental::optional 915 1.1 mrg template<typename _Tp> 916 1.1 mrg struct hash<experimental::optional<_Tp>> 917 1.1 mrg { 918 1.1 mrg using result_type = size_t; 919 1.1 mrg using argument_type = experimental::optional<_Tp>; 920 1.1 mrg 921 1.1 mrg size_t 922 1.1 mrg operator()(const experimental::optional<_Tp>& __t) const 923 1.1 mrg noexcept(noexcept(hash<_Tp> {}(*__t))) 924 1.1 mrg { 925 1.1 mrg // We pick an arbitrary hash for disengaged optionals which hopefully 926 1.1 mrg // usual values of _Tp won't typically hash to. 927 1.1 mrg constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333); 928 1.1 mrg return __t ? hash<_Tp> {}(*__t) : __magic_disengaged_hash; 929 1.1 mrg } 930 1.1 mrg }; 931 1.4 mrg 932 1.4 mrg _GLIBCXX_END_NAMESPACE_VERSION 933 1.4 mrg } // namespace std 934 1.1 mrg 935 1.1 mrg #endif // C++14 936 1.1 mrg 937 1.1 mrg #endif // _GLIBCXX_EXPERIMENTAL_OPTIONAL 938