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