1// Copyright (C) 2011 - 2012 Andrzej Krzemienski.
2//
3// Use, modification, and distribution is subject to the Boost Software
4// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5// http://www.boost.org/LICENSE_1_0.txt)
6//
7// The idea and interface is based on Boost.Optional library
8// authored by Fernando Luis Cacciola Carballal
9//
10// Boost Software License - Version 1.0 - August 17th, 2003
11//
12// Permission is hereby granted, free of charge, to any person or organization
13// obtaining a copy of the software and accompanying documentation covered by
14// this license (the "Software") to use, reproduce, display, distribute,
15// execute, and transmit the Software, and to prepare derivative works of the
16// Software, and to permit third-parties to whom the Software is furnished to
17// do so, all subject to the following:
18//
19// The copyright notices in the Software and this entire statement, including
20// the above license grant, this restriction and the following disclaimer,
21// must be included in all copies of the Software, in whole or in part, and
22// all derivative works of the Software, unless such copies or derivative
23// works are solely in the form of machine-executable object code generated by
24// a source language processor.
25//
26// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
29// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
30// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
31// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
32// DEALINGS IN THE SOFTWARE.
33
34// Copied from https://github.com/akrzemi1/Optional (8456c3923776b33b4ae852734273fe934c3e4e61)
35
36// Modified to make it compile with exceptions disabled.
37
38#pragma once
39
40# include <utility>
41# include <type_traits>
42# include <initializer_list>
43# include <cassert>
44# include <string>
45# include <stdexcept>
46# include <wtf/Assertions.h>
47# include <wtf/Compiler.h>
48# include <wtf/StdLibExtras.h>
49
50# define TR2_OPTIONAL_REQUIRES(...) typename std::enable_if<__VA_ARGS__::value, bool>::type = false
51
52# if defined __GNUC__ // NOTE: GNUC is also defined for Clang
53# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)
54# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
55# elif (__GNUC__ > 4)
56# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
57# endif
58#
59# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)
60# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___
61# elif (__GNUC__ > 4)
62# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___
63# endif
64#
65# if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ >= 1)
66# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
67# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)
68# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
69# elif (__GNUC__ > 4)
70# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
71# endif
72# endif
73#
74# if defined __clang_major__
75# if (__clang_major__ == 3 && __clang_minor__ >= 5)
76# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_
77# elif (__clang_major__ > 3)
78# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_
79# endif
80# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_
81# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
82# elif (__clang_major__ == 3 && __clang_minor__ == 4 && __clang_patchlevel__ >= 2)
83# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
84# endif
85# endif
86#
87# if defined _MSC_VER
88# if (_MSC_VER >= 1900)
89# define TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
90# endif
91# endif
92
93# if defined __clang__
94# if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9)
95# define OPTIONAL_HAS_THIS_RVALUE_REFS 1
96# else
97# define OPTIONAL_HAS_THIS_RVALUE_REFS 0
98# endif
99# elif defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
100# define OPTIONAL_HAS_THIS_RVALUE_REFS 1
101# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
102# define OPTIONAL_HAS_THIS_RVALUE_REFS 1
103# else
104# define OPTIONAL_HAS_THIS_RVALUE_REFS 0
105# endif
106
107
108# if defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
109# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1
110# define OPTIONAL_CONSTEXPR_INIT_LIST constexpr
111# else
112# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0
113# define OPTIONAL_CONSTEXPR_INIT_LIST
114# endif
115
116# // In C++11 constexpr implies const, so we need to make non-const members also non-constexpr
117# if (defined __cplusplus) && (__cplusplus == 201103L)
118# define OPTIONAL_MUTABLE_CONSTEXPR
119# else
120# define OPTIONAL_MUTABLE_CONSTEXPR constexpr
121# endif
122
123#if COMPILER_SUPPORTS(EXCEPTIONS)
124#define __THROW_EXCEPTION(__exception) throw __exception;
125#define __NOEXCEPT noexcept
126#define __NOEXCEPT_(__exception) noexcept(__exception)
127#else
128#define __THROW_EXCEPTION(__exception) do { (void)__exception; CRASH(); } while (0);
129#define __NOEXCEPT
130#define __NOEXCEPT_(...)
131#endif
132
133namespace WTF {
134namespace detail_ {
135
136// NOTE: All our target compilers support is_trivially_destructible.
137// // BEGIN workaround for missing is_trivially_destructible
138// # if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
139// // leave it: it is already there
140// # elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
141// // leave it: it is already there
142// # elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
143// // leave it: it is already there
144// # elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS
145// // leave it: the user doesn't want it
146// # else
147// template <typename T>
148// using is_trivially_destructible = std::has_trivial_destructor<T>;
149// # endif
150// // END workaround for missing is_trivially_destructible
151
152#if COMPILER_SUPPORTS(EXCEPTIONS)
153# if defined(TR2_OPTIONAL_GCC_4_7_AND_HIGHER___) || defined(TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_) || defined(TR2_OPTIONAL_MSVC_2015_AND_HIGHER___)
154 // leave it; our metafunctions are already defined.
155 template <typename T>
156 using is_nothrow_move_constructible = std::is_nothrow_move_constructible<T>;
157 template <typename T>
158 using is_nothrow_move_assignable = std::is_nothrow_move_assignable<T>;
159# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS
160 // leave it: the user doesn't want it
161# else
162
163
164// workaround for missing traits in GCC and CLANG
165template <class T>
166struct is_nothrow_move_constructible
167{
168 constexpr static bool value = std::is_nothrow_constructible<T, T&&>::value;
169};
170
171
172template <class T, class U>
173struct is_assignable
174{
175 template <class X, class Y>
176 constexpr static bool has_assign(...) { return false; }
177
178 template <class X, class Y, size_t S = sizeof((std::declval<X>() = std::declval<Y>(), true)) >
179 // the comma operator is necessary for the cases where operator= returns void
180 constexpr static bool has_assign(bool) { return true; }
181
182 constexpr static bool value = has_assign<T, U>(true);
183};
184
185
186template <class T>
187struct is_nothrow_move_assignable
188{
189 template <class X, bool has_any_move_assign>
190 struct has_nothrow_move_assign {
191 constexpr static bool value = false;
192 };
193
194 template <class X>
195 struct has_nothrow_move_assign<X, true> {
196 constexpr static bool value = __NOEXCEPT_( std::declval<X&>() = std::declval<X&&>() );
197 };
198
199 constexpr static bool value = has_nothrow_move_assign<T, is_assignable<T&, T&&>::value>::value;
200};
201// end workaround
202
203
204# endif
205#endif
206
207} // namespace detail_
208
209// 20.5.4, Optional for object types
210template <class T> class Optional;
211
212// 20.5.5, Optional for lvalue reference types
213template <class T> class Optional<T&>;
214
215namespace detail_ {
216
217// workaround: std utility functions aren't constexpr yet
218template <class T> constexpr T&& constexpr_forward(typename std::remove_reference<T>::type& t) __NOEXCEPT
219{
220 return static_cast<T&&>(t);
221}
222
223template <class T> constexpr T&& constexpr_forward(typename std::remove_reference<T>::type&& t) __NOEXCEPT
224{
225 static_assert(!std::is_lvalue_reference<T>::value, "!!");
226 return static_cast<T&&>(t);
227}
228
229template <class T> constexpr typename std::remove_reference<T>::type&& constexpr_move(T&& t) __NOEXCEPT
230{
231 return static_cast<typename std::remove_reference<T>::type&&>(t);
232}
233
234
235// static_addressof: a constexpr version of addressof
236template <typename T>
237struct has_overloaded_addressof
238{
239 template <class X>
240 constexpr static bool has_overload(...) { return false; }
241
242 template <class X, size_t S = sizeof(std::declval<X&>().operator&()) >
243 constexpr static bool has_overload(bool) { return true; }
244
245 constexpr static bool value = has_overload<T>(true);
246};
247
248template <typename T, TR2_OPTIONAL_REQUIRES(!has_overloaded_addressof<T>)>
249constexpr T* static_addressof(T& ref)
250{
251 return &ref;
252}
253
254template <typename T, TR2_OPTIONAL_REQUIRES(has_overloaded_addressof<T>)>
255T* static_addressof(T& ref)
256{
257 return std::addressof(ref);
258}
259
260
261// the call to convert<A>(b) has return type A and converts b to type A iff b decltype(b) is implicitly convertible to A
262template <class U>
263constexpr U convert(U v) { return v; }
264
265} // namespace detail
266
267
268constexpr struct trivial_init_t{} trivial_init{};
269
270
271// 20.5.7, Disengaged state indicator
272struct nullopt_t
273{
274 struct init{};
275 constexpr explicit nullopt_t(init){}
276};
277constexpr nullopt_t nullopt{nullopt_t::init()};
278
279
280template <class T>
281union storage_t
282{
283 unsigned char dummy_;
284 T value_;
285
286 constexpr storage_t( trivial_init_t ) __NOEXCEPT : dummy_() {};
287
288 template <class... Args>
289 constexpr storage_t( Args&&... args ) : value_(detail_::constexpr_forward<Args>(args)...) {}
290
291 ~storage_t(){}
292};
293
294
295template <class T>
296union constexpr_storage_t
297{
298 unsigned char dummy_;
299 T value_;
300
301 constexpr constexpr_storage_t( trivial_init_t ) __NOEXCEPT : dummy_() {};
302
303 template <class... Args>
304 constexpr constexpr_storage_t( Args&&... args ) : value_(detail_::constexpr_forward<Args>(args)...) {}
305
306 ~constexpr_storage_t() = default;
307};
308
309
310template <class T>
311struct Optional_base
312{
313 bool init_;
314 storage_t<T> storage_;
315
316 constexpr Optional_base() __NOEXCEPT : init_(false), storage_(trivial_init) {};
317
318 explicit constexpr Optional_base(const T& v) : init_(true), storage_(v) {}
319
320 explicit constexpr Optional_base(T&& v) : init_(true), storage_(detail_::constexpr_move(v)) {}
321
322 template <class... Args> explicit Optional_base(std::in_place_t, Args&&... args)
323 : init_(true), storage_(detail_::constexpr_forward<Args>(args)...) {}
324
325 template <class U, class... Args, TR2_OPTIONAL_REQUIRES(std::is_constructible<T, std::initializer_list<U>>)>
326 explicit Optional_base(std::in_place_t, std::initializer_list<U> il, Args&&... args)
327 : init_(true), storage_(il, std::forward<Args>(args)...) {}
328
329 ~Optional_base() { if (init_) storage_.value_.T::~T(); }
330};
331
332
333template <class T>
334struct constexpr_Optional_base
335{
336 bool init_;
337 constexpr_storage_t<T> storage_;
338
339 constexpr constexpr_Optional_base() __NOEXCEPT : init_(false), storage_(trivial_init) {};
340
341 explicit constexpr constexpr_Optional_base(const T& v) : init_(true), storage_(v) {}
342
343 explicit constexpr constexpr_Optional_base(T&& v) : init_(true), storage_(detail_::constexpr_move(v)) {}
344
345 template <class... Args> explicit constexpr constexpr_Optional_base(std::in_place_t, Args&&... args)
346 : init_(true), storage_(detail_::constexpr_forward<Args>(args)...) {}
347
348 template <class U, class... Args, TR2_OPTIONAL_REQUIRES(std::is_constructible<T, std::initializer_list<U>>)>
349 OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_Optional_base(std::in_place_t, std::initializer_list<U> il, Args&&... args)
350 : init_(true), storage_(il, std::forward<Args>(args)...) {}
351
352 ~constexpr_Optional_base() = default;
353};
354
355template <class T>
356using OptionalBase = typename std::conditional<
357 std::is_trivially_destructible<T>::value, // if possible
358 constexpr_Optional_base<typename std::remove_const<T>::type>, // use base with trivial destructor
359 Optional_base<typename std::remove_const<T>::type>
360>::type;
361
362
363
364template <class T>
365class Optional : private OptionalBase<T>
366{
367 static_assert( !std::is_same<typename std::decay<T>::type, nullopt_t>::value, "bad T" );
368 static_assert( !std::is_same<typename std::decay<T>::type, std::in_place_t>::value, "bad T" );
369
370
371 constexpr bool initialized() const __NOEXCEPT { return OptionalBase<T>::init_; }
372 typename std::remove_const<T>::type* dataptr() { return std::addressof(OptionalBase<T>::storage_.value_); }
373 constexpr const T* dataptr() const { return detail_::static_addressof(OptionalBase<T>::storage_.value_); }
374
375# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1
376 constexpr const T& contained_val() const& { return OptionalBase<T>::storage_.value_; }
377 OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && { return std::move(OptionalBase<T>::storage_.value_); }
378 OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & { return OptionalBase<T>::storage_.value_; }
379# else
380 constexpr const T& contained_val() const { return OptionalBase<T>::storage_.value_; }
381 T& contained_val() { return OptionalBase<T>::storage_.value_; }
382# endif
383
384 void clear() __NOEXCEPT {
385 if (initialized()) dataptr()->T::~T();
386 OptionalBase<T>::init_ = false;
387 }
388
389 template <class... Args>
390 void initialize(Args&&... args) __NOEXCEPT_(__NOEXCEPT_(T(std::forward<Args>(args)...)))
391 {
392 ASSERT(!OptionalBase<T>::init_);
393 ::new (static_cast<void*>(dataptr())) T(std::forward<Args>(args)...);
394 OptionalBase<T>::init_ = true;
395 }
396
397 template <class U, class... Args>
398 void initialize(std::initializer_list<U> il, Args&&... args) __NOEXCEPT_(__NOEXCEPT_(T(il, std::forward<Args>(args)...)))
399 {
400 ASSERT(!OptionalBase<T>::init_);
401 ::new (static_cast<void*>(dataptr())) T(il, std::forward<Args>(args)...);
402 OptionalBase<T>::init_ = true;
403 }
404
405public:
406 typedef T value_type;
407
408 // 20.5.5.1, constructors
409 constexpr Optional() __NOEXCEPT : OptionalBase<T>() {};
410 constexpr Optional(nullopt_t) __NOEXCEPT : OptionalBase<T>() {};
411
412 Optional(const Optional& rhs)
413 : OptionalBase<T>()
414 {
415 if (rhs.initialized()) {
416 ::new (static_cast<void*>(dataptr())) T(*rhs);
417 OptionalBase<T>::init_ = true;
418 }
419 }
420
421 Optional(Optional&& rhs) __NOEXCEPT_(detail_::is_nothrow_move_constructible<T>::value)
422 : OptionalBase<T>()
423 {
424 if (rhs.initialized()) {
425 ::new (static_cast<void*>(dataptr())) T(std::move(*rhs));
426 OptionalBase<T>::init_ = true;
427 rhs.clear();
428 }
429 }
430
431 constexpr Optional(const T& v) : OptionalBase<T>(v) {}
432
433 constexpr Optional(T&& v) : OptionalBase<T>(detail_::constexpr_move(v)) {}
434
435 template <class... Args>
436 explicit constexpr Optional(std::in_place_t, Args&&... args)
437 : OptionalBase<T>(std::in_place_t{}, detail_::constexpr_forward<Args>(args)...) {}
438
439 template <class U, class... Args, TR2_OPTIONAL_REQUIRES(std::is_constructible<T, std::initializer_list<U>>)>
440 OPTIONAL_CONSTEXPR_INIT_LIST explicit Optional(std::in_place_t, std::initializer_list<U> il, Args&&... args)
441 : OptionalBase<T>(std::in_place_t{}, il, detail_::constexpr_forward<Args>(args)...) {}
442
443 // 20.5.4.2, Destructor
444 ~Optional() = default;
445
446 // 20.5.4.3, assignment
447 Optional& operator=(nullopt_t) __NOEXCEPT
448 {
449 clear();
450 return *this;
451 }
452
453 Optional& operator=(const Optional& rhs)
454 {
455 if (initialized() == true && rhs.initialized() == false) clear();
456 else if (initialized() == false && rhs.initialized() == true) initialize(*rhs);
457 else if (initialized() == true && rhs.initialized() == true) contained_val() = *rhs;
458 return *this;
459 }
460
461 Optional& operator=(Optional&& rhs)
462 __NOEXCEPT_(detail_::is_nothrow_move_assignable<T>::value && detail_::is_nothrow_move_constructible<T>::value)
463 {
464 if (initialized() == true && rhs.initialized() == false) clear();
465 else if (initialized() == false && rhs.initialized() == true) { initialize(std::move(*rhs)); rhs.clear(); }
466 else if (initialized() == true && rhs.initialized() == true) { contained_val() = std::move(*rhs); rhs.clear(); }
467 return *this;
468 }
469
470 template <class U>
471 auto operator=(U&& v)
472 -> typename std::enable_if
473 <
474 std::is_same<typename std::decay<U>::type, T>::value,
475 Optional&
476 >::type
477 {
478 if (initialized()) { contained_val() = std::forward<U>(v); }
479 else { initialize(std::forward<U>(v)); }
480 return *this;
481 }
482
483
484 template <class... Args>
485 void emplace(Args&&... args)
486 {
487 clear();
488 initialize(std::forward<Args>(args)...);
489 }
490
491 template <class U, class... Args>
492 void emplace(std::initializer_list<U> il, Args&&... args)
493 {
494 clear();
495 initialize<U, Args...>(il, std::forward<Args>(args)...);
496 }
497
498 // 20.5.4.4, Swap
499 void swap(Optional<T>& rhs) __NOEXCEPT_(detail_::is_nothrow_move_constructible<T>::value && __NOEXCEPT_(swap(std::declval<T&>(), std::declval<T&>())))
500 {
501 if (initialized() == true && rhs.initialized() == false) { rhs.initialize(std::move(**this)); clear(); }
502 else if (initialized() == false && rhs.initialized() == true) { initialize(std::move(*rhs)); rhs.clear(); }
503 else if (initialized() == true && rhs.initialized() == true) { using std::swap; swap(**this, *rhs); }
504 }
505
506 // 20.5.4.5, Observers
507
508 explicit constexpr operator bool() const __NOEXCEPT { return initialized(); }
509 constexpr bool hasValue() const __NOEXCEPT { return initialized(); }
510
511 constexpr T const* operator ->() const {
512 RELEASE_ASSERT_UNDER_CONSTEXPR_CONTEXT(initialized());
513 return dataptr();
514 }
515
516 OPTIONAL_MUTABLE_CONSTEXPR T* operator ->() {
517 RELEASE_ASSERT_UNDER_CONSTEXPR_CONTEXT(initialized());
518 return dataptr();
519 }
520
521 constexpr T const& operator *() const& {
522 RELEASE_ASSERT_UNDER_CONSTEXPR_CONTEXT(initialized());
523 return contained_val();
524 }
525
526 OPTIONAL_MUTABLE_CONSTEXPR T& operator *() & {
527 RELEASE_ASSERT_UNDER_CONSTEXPR_CONTEXT(initialized());
528 return contained_val();
529 }
530
531 OPTIONAL_MUTABLE_CONSTEXPR T&& operator *() && {
532 RELEASE_ASSERT_UNDER_CONSTEXPR_CONTEXT(initialized());
533 return detail_::constexpr_move(contained_val());
534 }
535
536 constexpr T const& value() const& {
537 RELEASE_ASSERT_UNDER_CONSTEXPR_CONTEXT(initialized());
538 return contained_val();
539 }
540
541 OPTIONAL_MUTABLE_CONSTEXPR T& value() & {
542 RELEASE_ASSERT_UNDER_CONSTEXPR_CONTEXT(initialized());
543 return contained_val();
544 }
545
546 OPTIONAL_MUTABLE_CONSTEXPR T&& value() && {
547 RELEASE_ASSERT_UNDER_CONSTEXPR_CONTEXT(initialized());
548 return std::move(contained_val());
549 }
550
551# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1
552
553 template <class V>
554 constexpr T valueOr(V&& v) const&
555 {
556 return *this ? **this : detail_::convert<T>(detail_::constexpr_forward<V>(v));
557 }
558
559 template <class V>
560 OPTIONAL_MUTABLE_CONSTEXPR T valueOr(V&& v) &&
561 {
562 return *this ? detail_::constexpr_move(const_cast<Optional<T>&>(*this).contained_val()) : detail_::convert<T>(detail_::constexpr_forward<V>(v));
563 }
564
565# else
566
567 template <class V>
568 constexpr T valueOr(V&& v) const
569 {
570 return *this ? **this : detail_::convert<T>(detail_::constexpr_forward<V>(v));
571 }
572
573# endif
574
575 // 20.6.3.6, modifiers
576 void reset() __NOEXCEPT { clear(); }
577};
578
579
580template <class T>
581class Optional<T&>
582{
583 static_assert( !std::is_same<T, nullopt_t>::value, "bad T" );
584 static_assert( !std::is_same<T, std::in_place_t>::value, "bad T" );
585 T* ref;
586
587public:
588
589 // 20.5.5.1, construction/destruction
590 constexpr Optional() __NOEXCEPT : ref(nullptr) {}
591
592 constexpr Optional(nullopt_t) __NOEXCEPT : ref(nullptr) {}
593
594 constexpr Optional(T& v) __NOEXCEPT : ref(detail_::static_addressof(v)) {}
595
596 Optional(T&&) = delete;
597
598 constexpr Optional(const Optional& rhs) __NOEXCEPT : ref(rhs.ref) {}
599
600 explicit constexpr Optional(std::in_place_t, T& v) __NOEXCEPT : ref(detail_::static_addressof(v)) {}
601
602 explicit Optional(std::in_place_t, T&&) = delete;
603
604 ~Optional() = default;
605
606 // 20.5.5.2, mutation
607 Optional& operator=(nullopt_t) __NOEXCEPT {
608 ref = nullptr;
609 return *this;
610 }
611
612 // Optional& operator=(const Optional& rhs) __NOEXCEPT {
613 // ref = rhs.ref;
614 // return *this;
615 // }
616
617 // Optional& operator=(Optional&& rhs) __NOEXCEPT {
618 // ref = rhs.ref;
619 // return *this;
620 // }
621
622 template <typename U>
623 auto operator=(U&& rhs) __NOEXCEPT
624 -> typename std::enable_if
625 <
626 std::is_same<typename std::decay<U>::type, Optional<T&>>::value,
627 Optional&
628 >::type
629 {
630 ref = rhs.ref;
631 return *this;
632 }
633
634 template <typename U>
635 auto operator=(U&& rhs) __NOEXCEPT
636 -> typename std::enable_if
637 <
638 !std::is_same<typename std::decay<U>::type, Optional<T&>>::value,
639 Optional&
640 >::type
641 = delete;
642
643 void emplace(T& v) __NOEXCEPT {
644 ref = detail_::static_addressof(v);
645 }
646
647 void emplace(T&&) = delete;
648
649
650 void swap(Optional<T&>& rhs) __NOEXCEPT
651 {
652 std::swap(ref, rhs.ref);
653 }
654
655 // 20.5.5.3, observers
656 constexpr T* operator->() const {
657 RELEASE_ASSERT_UNDER_CONSTEXPR_CONTEXT(ref);
658 return ref;
659 }
660
661 constexpr T& operator*() const {
662 RELEASE_ASSERT_UNDER_CONSTEXPR_CONTEXT(ref);
663 return *ref;
664 }
665
666 constexpr T& value() const {
667 RELEASE_ASSERT_UNDER_CONSTEXPR_CONTEXT(ref());
668 return *ref;
669 }
670
671 explicit constexpr operator bool() const __NOEXCEPT {
672 return ref != nullptr;
673 }
674
675 constexpr bool hasValue() const __NOEXCEPT {
676 return ref != nullptr;
677 }
678
679 template <class V>
680 constexpr typename std::decay<T>::type valueOr(V&& v) const
681 {
682 return *this ? **this : detail_::convert<typename std::decay<T>::type>(detail_::constexpr_forward<V>(v));
683 }
684
685 // x.x.x.x, modifiers
686 void reset() __NOEXCEPT { ref = nullptr; }
687};
688
689
690template <class T>
691class Optional<T&&>
692{
693 static_assert( sizeof(T) == 0, "Optional rvalue references disallowed" );
694};
695
696
697// 20.5.8, Relational operators
698template <class T> constexpr bool operator==(const Optional<T>& x, const Optional<T>& y)
699{
700 return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y;
701}
702
703template <class T> constexpr bool operator!=(const Optional<T>& x, const Optional<T>& y)
704{
705 return !(x == y);
706}
707
708template <class T> constexpr bool operator<(const Optional<T>& x, const Optional<T>& y)
709{
710 return (!y) ? false : (!x) ? true : *x < *y;
711}
712
713template <class T> constexpr bool operator>(const Optional<T>& x, const Optional<T>& y)
714{
715 return (y < x);
716}
717
718template <class T> constexpr bool operator<=(const Optional<T>& x, const Optional<T>& y)
719{
720 return !(y < x);
721}
722
723template <class T> constexpr bool operator>=(const Optional<T>& x, const Optional<T>& y)
724{
725 return !(x < y);
726}
727
728
729// 20.5.9, Comparison with nullopt
730template <class T> constexpr bool operator==(const Optional<T>& x, nullopt_t) __NOEXCEPT
731{
732 return (!x);
733}
734
735template <class T> constexpr bool operator==(nullopt_t, const Optional<T>& x) __NOEXCEPT
736{
737 return (!x);
738}
739
740template <class T> constexpr bool operator!=(const Optional<T>& x, nullopt_t) __NOEXCEPT
741{
742 return bool(x);
743}
744
745template <class T> constexpr bool operator!=(nullopt_t, const Optional<T>& x) __NOEXCEPT
746{
747 return bool(x);
748}
749
750template <class T> constexpr bool operator<(const Optional<T>&, nullopt_t) __NOEXCEPT
751{
752 return false;
753}
754
755template <class T> constexpr bool operator<(nullopt_t, const Optional<T>& x) __NOEXCEPT
756{
757 return bool(x);
758}
759
760template <class T> constexpr bool operator<=(const Optional<T>& x, nullopt_t) __NOEXCEPT
761{
762 return (!x);
763}
764
765template <class T> constexpr bool operator<=(nullopt_t, const Optional<T>&) __NOEXCEPT
766{
767 return true;
768}
769
770template <class T> constexpr bool operator>(const Optional<T>& x, nullopt_t) __NOEXCEPT
771{
772 return bool(x);
773}
774
775template <class T> constexpr bool operator>(nullopt_t, const Optional<T>&) __NOEXCEPT
776{
777 return false;
778}
779
780template <class T> constexpr bool operator>=(const Optional<T>&, nullopt_t) __NOEXCEPT
781{
782 return true;
783}
784
785template <class T> constexpr bool operator>=(nullopt_t, const Optional<T>& x) __NOEXCEPT
786{
787 return (!x);
788}
789
790
791
792// 20.5.10, Comparison with T
793template <class T> constexpr bool operator==(const Optional<T>& x, const T& v)
794{
795 return bool(x) ? *x == v : false;
796}
797
798template <class T> constexpr bool operator==(const T& v, const Optional<T>& x)
799{
800 return bool(x) ? v == *x : false;
801}
802
803template <class T> constexpr bool operator!=(const Optional<T>& x, const T& v)
804{
805 return bool(x) ? *x != v : true;
806}
807
808template <class T> constexpr bool operator!=(const T& v, const Optional<T>& x)
809{
810 return bool(x) ? v != *x : true;
811}
812
813template <class T> constexpr bool operator<(const Optional<T>& x, const T& v)
814{
815 return bool(x) ? *x < v : true;
816}
817
818template <class T> constexpr bool operator>(const T& v, const Optional<T>& x)
819{
820 return bool(x) ? v > *x : true;
821}
822
823template <class T> constexpr bool operator>(const Optional<T>& x, const T& v)
824{
825 return bool(x) ? *x > v : false;
826}
827
828template <class T> constexpr bool operator<(const T& v, const Optional<T>& x)
829{
830 return bool(x) ? v < *x : false;
831}
832
833template <class T> constexpr bool operator>=(const Optional<T>& x, const T& v)
834{
835 return bool(x) ? *x >= v : false;
836}
837
838template <class T> constexpr bool operator<=(const T& v, const Optional<T>& x)
839{
840 return bool(x) ? v <= *x : false;
841}
842
843template <class T> constexpr bool operator<=(const Optional<T>& x, const T& v)
844{
845 return bool(x) ? *x <= v : true;
846}
847
848template <class T> constexpr bool operator>=(const T& v, const Optional<T>& x)
849{
850 return bool(x) ? v >= *x : true;
851}
852
853
854// Comparison of Optional<T&> with T
855template <class T> constexpr bool operator==(const Optional<T&>& x, const T& v)
856{
857 return bool(x) ? *x == v : false;
858}
859
860template <class T> constexpr bool operator==(const T& v, const Optional<T&>& x)
861{
862 return bool(x) ? v == *x : false;
863}
864
865template <class T> constexpr bool operator!=(const Optional<T&>& x, const T& v)
866{
867 return bool(x) ? *x != v : true;
868}
869
870template <class T> constexpr bool operator!=(const T& v, const Optional<T&>& x)
871{
872 return bool(x) ? v != *x : true;
873}
874
875template <class T> constexpr bool operator<(const Optional<T&>& x, const T& v)
876{
877 return bool(x) ? *x < v : true;
878}
879
880template <class T> constexpr bool operator>(const T& v, const Optional<T&>& x)
881{
882 return bool(x) ? v > *x : true;
883}
884
885template <class T> constexpr bool operator>(const Optional<T&>& x, const T& v)
886{
887 return bool(x) ? *x > v : false;
888}
889
890template <class T> constexpr bool operator<(const T& v, const Optional<T&>& x)
891{
892 return bool(x) ? v < *x : false;
893}
894
895template <class T> constexpr bool operator>=(const Optional<T&>& x, const T& v)
896{
897 return bool(x) ? *x >= v : false;
898}
899
900template <class T> constexpr bool operator<=(const T& v, const Optional<T&>& x)
901{
902 return bool(x) ? v <= *x : false;
903}
904
905template <class T> constexpr bool operator<=(const Optional<T&>& x, const T& v)
906{
907 return bool(x) ? *x <= v : true;
908}
909
910template <class T> constexpr bool operator>=(const T& v, const Optional<T&>& x)
911{
912 return bool(x) ? v >= *x : true;
913}
914
915// Comparison of Optional<T const&> with T
916template <class T> constexpr bool operator==(const Optional<const T&>& x, const T& v)
917{
918 return bool(x) ? *x == v : false;
919}
920
921template <class T> constexpr bool operator==(const T& v, const Optional<const T&>& x)
922{
923 return bool(x) ? v == *x : false;
924}
925
926template <class T> constexpr bool operator!=(const Optional<const T&>& x, const T& v)
927{
928 return bool(x) ? *x != v : true;
929}
930
931template <class T> constexpr bool operator!=(const T& v, const Optional<const T&>& x)
932{
933 return bool(x) ? v != *x : true;
934}
935
936template <class T> constexpr bool operator<(const Optional<const T&>& x, const T& v)
937{
938 return bool(x) ? *x < v : true;
939}
940
941template <class T> constexpr bool operator>(const T& v, const Optional<const T&>& x)
942{
943 return bool(x) ? v > *x : true;
944}
945
946template <class T> constexpr bool operator>(const Optional<const T&>& x, const T& v)
947{
948 return bool(x) ? *x > v : false;
949}
950
951template <class T> constexpr bool operator<(const T& v, const Optional<const T&>& x)
952{
953 return bool(x) ? v < *x : false;
954}
955
956template <class T> constexpr bool operator>=(const Optional<const T&>& x, const T& v)
957{
958 return bool(x) ? *x >= v : false;
959}
960
961template <class T> constexpr bool operator<=(const T& v, const Optional<const T&>& x)
962{
963 return bool(x) ? v <= *x : false;
964}
965
966template <class T> constexpr bool operator<=(const Optional<const T&>& x, const T& v)
967{
968 return bool(x) ? *x <= v : true;
969}
970
971template <class T> constexpr bool operator>=(const T& v, const Optional<const T&>& x)
972{
973 return bool(x) ? v >= *x : true;
974}
975
976
977// 20.5.12, Specialized algorithms
978template <class T>
979void swap(Optional<T>& x, Optional<T>& y) __NOEXCEPT_(__NOEXCEPT_(x.swap(y)))
980{
981 x.swap(y);
982}
983
984
985template <class T>
986constexpr Optional<typename std::decay<T>::type> makeOptional(T&& v)
987{
988 return Optional<typename std::decay<T>::type>(detail_::constexpr_forward<T>(v));
989}
990
991template <class X>
992constexpr Optional<X&> makeOptional(std::reference_wrapper<X> v)
993{
994 return Optional<X&>(v.get());
995}
996
997} // namespace WTF
998
999namespace std
1000{
1001 template <typename T>
1002 struct hash<WTF::Optional<T>>
1003 {
1004 typedef typename hash<T>::result_type result_type;
1005 typedef WTF::Optional<T> argument_type;
1006
1007 constexpr result_type operator()(argument_type const& arg) const {
1008 return arg ? std::hash<T>{}(*arg) : result_type{};
1009 }
1010 };
1011
1012 template <typename T>
1013 struct hash<WTF::Optional<T&>>
1014 {
1015 typedef typename hash<T>::result_type result_type;
1016 typedef WTF::Optional<T&> argument_type;
1017
1018 constexpr result_type operator()(argument_type const& arg) const {
1019 return arg ? std::hash<T>{}(*arg) : result_type{};
1020 }
1021 };
1022}
1023
1024# undef TR2_OPTIONAL_REQUIRES
1025
1026namespace WTF {
1027
1028// -- WebKit Additions --
1029template <class OptionalType, class Callback>
1030ALWAYS_INLINE
1031auto valueOrCompute(OptionalType Optional, Callback callback) -> typename OptionalType::value_type
1032{
1033 if (Optional)
1034 return *Optional;
1035 return callback();
1036}
1037
1038} // namespace WTF
1039
1040using WTF::Optional;
1041using WTF::makeOptional;
1042using WTF::valueOrCompute;
1043