1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef BASE_OPTIONAL_H_
6 #define BASE_OPTIONAL_H_
12 #include "base/check.h"
13 #include "base/template_util.h"
18 // http://en.cppreference.com/w/cpp/utility/optional/nullopt_t
20 constexpr explicit nullopt_t(int) {}
24 // http://en.cppreference.com/w/cpp/utility/optional/nullopt
25 constexpr nullopt_t nullopt(0);
27 // Forward declaration, which is refered by following helpers.
33 struct DummyUnionMember {};
35 template <typename T, bool = std::is_trivially_destructible<T>::value>
36 struct OptionalStorageBase {
37 // Provide non-defaulted default ctor to make sure it's not deleted by
38 // non-trivial T::T() in the union.
39 constexpr OptionalStorageBase() : dummy_() {}
41 template <class... Args>
42 constexpr explicit OptionalStorageBase(in_place_t, Args&&... args)
43 : is_populated_(true), value_(std::forward<Args>(args)...) {}
45 // When T is not trivially destructible we must call its
46 // destructor before deallocating its memory.
47 // Note that this hides the (implicitly declared) move constructor, which
48 // would be used for constexpr move constructor in OptionalStorage<T>.
49 // It is needed iff T is trivially move constructible. However, the current
50 // is_trivially_{copy,move}_constructible implementation requires
51 // is_trivially_destructible (which looks a bug, cf:
52 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51452 and
53 // http://cplusplus.github.io/LWG/lwg-active.html#2116), so it is not
54 // necessary for this case at the moment. Please see also the destructor
55 // comment in "is_trivially_destructible = true" specialization below.
56 ~OptionalStorageBase() {
61 template <class... Args>
62 void Init(Args&&... args) {
63 DCHECK(!is_populated_);
64 ::new (&value_) T(std::forward<Args>(args)...);
68 bool is_populated_ = false;
70 // |dummy_| exists so that the union will always be initialized, even when
71 // it doesn't contain a value. Union members must be initialized for the
72 // constructor to be 'constexpr'. Having a special trivial class for it is
73 // better than e.g. using char, because the latter will have to be
74 // zero-initialized, and the compiler can't optimize this write away, since
75 // it assumes this might be a programmer's invariant. This can also cause
76 // problems for conservative GC in Oilpan. Compiler is free to split shared
77 // and non-shared parts of the union in separate memory locations (or
78 // registers). If conservative GC is triggered at this moment, the stack
79 // scanning routine won't find the correct object pointed from
80 // Optional<HeapObject*>. This dummy valueless struct lets the compiler know
81 // that we don't care about the value of this union member.
82 DummyUnionMember dummy_;
88 struct OptionalStorageBase<T, true /* trivially destructible */> {
89 // Provide non-defaulted default ctor to make sure it's not deleted by
90 // non-trivial T::T() in the union.
91 constexpr OptionalStorageBase() : dummy_() {}
93 template <class... Args>
94 constexpr explicit OptionalStorageBase(in_place_t, Args&&... args)
95 : is_populated_(true), value_(std::forward<Args>(args)...) {}
97 // When T is trivially destructible (i.e. its destructor does nothing) there
98 // is no need to call it. Implicitly defined destructor is trivial, because
99 // both members (bool and union containing only variants which are trivially
100 // destructible) are trivially destructible.
101 // Explicitly-defaulted destructor is also trivial, but do not use it here,
102 // because it hides the implicit move constructor. It is needed to implement
103 // constexpr move constructor in OptionalStorage iff T is trivially move
104 // constructible. Note that, if T is trivially move constructible, the move
105 // constructor of OptionalStorageBase<T> is also implicitly defined and it is
106 // trivially move constructor. If T is not trivially move constructible,
107 // "not declaring move constructor without destructor declaration" here means
108 // "delete move constructor", which works because any move constructor of
109 // OptionalStorage will not refer to it in that case.
111 template <class... Args>
112 void Init(Args&&... args) {
113 DCHECK(!is_populated_);
114 ::new (&value_) T(std::forward<Args>(args)...);
115 is_populated_ = true;
118 bool is_populated_ = false;
120 // |dummy_| exists so that the union will always be initialized, even when
121 // it doesn't contain a value. Union members must be initialized for the
122 // constructor to be 'constexpr'. Having a special trivial class for it is
123 // better than e.g. using char, because the latter will have to be
124 // zero-initialized, and the compiler can't optimize this write away, since
125 // it assumes this might be a programmer's invariant. This can also cause
126 // problems for conservative GC in Oilpan. Compiler is free to split shared
127 // and non-shared parts of the union in separate memory locations (or
128 // registers). If conservative GC is triggered at this moment, the stack
129 // scanning routine won't find the correct object pointed from
130 // Optional<HeapObject*>. This dummy valueless struct lets the compiler know
131 // that we don't care about the value of this union member.
132 DummyUnionMember dummy_;
137 // Implement conditional constexpr copy and move constructors. These are
138 // constexpr if is_trivially_{copy,move}_constructible<T>::value is true
139 // respectively. If each is true, the corresponding constructor is defined as
140 // "= default;", which generates a constexpr constructor (In this case,
141 // the condition of constexpr-ness is satisfied because the base class also has
142 // compiler generated constexpr {copy,move} constructors). Note that
143 // placement-new is prohibited in constexpr.
144 template <typename T,
145 bool = is_trivially_copy_constructible<T>::value,
146 bool = std::is_trivially_move_constructible<T>::value>
147 struct OptionalStorage : OptionalStorageBase<T> {
148 // This is no trivially {copy,move} constructible case. Other cases are
149 // defined below as specializations.
151 // Accessing the members of template base class requires explicit
153 using OptionalStorageBase<T>::is_populated_;
154 using OptionalStorageBase<T>::value_;
155 using OptionalStorageBase<T>::Init;
157 // Inherit constructors (specifically, the in_place constructor).
158 using OptionalStorageBase<T>::OptionalStorageBase;
160 // User defined constructor deletes the default constructor.
161 // Define it explicitly.
162 OptionalStorage() = default;
164 OptionalStorage(const OptionalStorage& other) {
165 if (other.is_populated_)
169 OptionalStorage(OptionalStorage&& other) noexcept(
170 std::is_nothrow_move_constructible<T>::value) {
171 if (other.is_populated_)
172 Init(std::move(other.value_));
176 template <typename T>
177 struct OptionalStorage<T,
178 true /* trivially copy constructible */,
179 false /* trivially move constructible */>
180 : OptionalStorageBase<T> {
181 using OptionalStorageBase<T>::is_populated_;
182 using OptionalStorageBase<T>::value_;
183 using OptionalStorageBase<T>::Init;
184 using OptionalStorageBase<T>::OptionalStorageBase;
186 OptionalStorage() = default;
187 OptionalStorage(const OptionalStorage& other) = default;
189 OptionalStorage(OptionalStorage&& other) noexcept(
190 std::is_nothrow_move_constructible<T>::value) {
191 if (other.is_populated_)
192 Init(std::move(other.value_));
196 template <typename T>
197 struct OptionalStorage<T,
198 false /* trivially copy constructible */,
199 true /* trivially move constructible */>
200 : OptionalStorageBase<T> {
201 using OptionalStorageBase<T>::is_populated_;
202 using OptionalStorageBase<T>::value_;
203 using OptionalStorageBase<T>::Init;
204 using OptionalStorageBase<T>::OptionalStorageBase;
206 OptionalStorage() = default;
207 OptionalStorage(OptionalStorage&& other) = default;
209 OptionalStorage(const OptionalStorage& other) {
210 if (other.is_populated_)
215 template <typename T>
216 struct OptionalStorage<T,
217 true /* trivially copy constructible */,
218 true /* trivially move constructible */>
219 : OptionalStorageBase<T> {
220 // If both trivially {copy,move} constructible are true, it is not necessary
221 // to use user-defined constructors. So, just inheriting constructors
222 // from the base class works.
223 using OptionalStorageBase<T>::OptionalStorageBase;
226 // Base class to support conditionally usable copy-/move- constructors
227 // and assign operators.
228 template <typename T>
230 // This class provides implementation rather than public API, so everything
231 // should be hidden. Often we use composition, but we cannot in this case
232 // because of C++ language restriction.
234 constexpr OptionalBase() = default;
235 constexpr OptionalBase(const OptionalBase& other) = default;
236 constexpr OptionalBase(OptionalBase&& other) = default;
238 template <class... Args>
239 constexpr explicit OptionalBase(in_place_t, Args&&... args)
240 : storage_(in_place, std::forward<Args>(args)...) {}
242 // Implementation of converting constructors.
243 template <typename U>
244 explicit OptionalBase(const OptionalBase<U>& other) {
245 if (other.storage_.is_populated_)
246 storage_.Init(other.storage_.value_);
249 template <typename U>
250 explicit OptionalBase(OptionalBase<U>&& other) {
251 if (other.storage_.is_populated_)
252 storage_.Init(std::move(other.storage_.value_));
255 ~OptionalBase() = default;
257 OptionalBase& operator=(const OptionalBase& other) {
262 OptionalBase& operator=(OptionalBase&& other) noexcept(
263 std::is_nothrow_move_assignable<T>::value&&
264 std::is_nothrow_move_constructible<T>::value) {
265 MoveAssign(std::move(other));
269 template <typename U>
270 void CopyAssign(const OptionalBase<U>& other) {
271 if (other.storage_.is_populated_)
272 InitOrAssign(other.storage_.value_);
277 template <typename U>
278 void MoveAssign(OptionalBase<U>&& other) {
279 if (other.storage_.is_populated_)
280 InitOrAssign(std::move(other.storage_.value_));
285 template <typename U>
286 void InitOrAssign(U&& value) {
287 if (storage_.is_populated_)
288 storage_.value_ = std::forward<U>(value);
290 storage_.Init(std::forward<U>(value));
293 void FreeIfNeeded() {
294 if (!storage_.is_populated_)
296 storage_.value_.~T();
297 storage_.is_populated_ = false;
300 // For implementing conversion, allow access to other typed OptionalBase
302 template <typename U>
303 friend class OptionalBase;
305 OptionalStorage<T> storage_;
308 // The following {Copy,Move}{Constructible,Assignable} structs are helpers to
309 // implement constructor/assign-operator overloading. Specifically, if T is
310 // is not movable but copyable, Optional<T>'s move constructor should not
311 // participate in overload resolution. This inheritance trick implements that.
312 template <bool is_copy_constructible>
313 struct CopyConstructible {};
316 struct CopyConstructible<false> {
317 constexpr CopyConstructible() = default;
318 constexpr CopyConstructible(const CopyConstructible&) = delete;
319 constexpr CopyConstructible(CopyConstructible&&) = default;
320 CopyConstructible& operator=(const CopyConstructible&) = default;
321 CopyConstructible& operator=(CopyConstructible&&) = default;
324 template <bool is_move_constructible>
325 struct MoveConstructible {};
328 struct MoveConstructible<false> {
329 constexpr MoveConstructible() = default;
330 constexpr MoveConstructible(const MoveConstructible&) = default;
331 constexpr MoveConstructible(MoveConstructible&&) = delete;
332 MoveConstructible& operator=(const MoveConstructible&) = default;
333 MoveConstructible& operator=(MoveConstructible&&) = default;
336 template <bool is_copy_assignable>
337 struct CopyAssignable {};
340 struct CopyAssignable<false> {
341 constexpr CopyAssignable() = default;
342 constexpr CopyAssignable(const CopyAssignable&) = default;
343 constexpr CopyAssignable(CopyAssignable&&) = default;
344 CopyAssignable& operator=(const CopyAssignable&) = delete;
345 CopyAssignable& operator=(CopyAssignable&&) = default;
348 template <bool is_move_assignable>
349 struct MoveAssignable {};
352 struct MoveAssignable<false> {
353 constexpr MoveAssignable() = default;
354 constexpr MoveAssignable(const MoveAssignable&) = default;
355 constexpr MoveAssignable(MoveAssignable&&) = default;
356 MoveAssignable& operator=(const MoveAssignable&) = default;
357 MoveAssignable& operator=(MoveAssignable&&) = delete;
360 // Helper to conditionally enable converting constructors and assign operators.
361 template <typename T, typename U>
362 using IsConvertibleFromOptional =
363 disjunction<std::is_constructible<T, Optional<U>&>,
364 std::is_constructible<T, const Optional<U>&>,
365 std::is_constructible<T, Optional<U>&&>,
366 std::is_constructible<T, const Optional<U>&&>,
367 std::is_convertible<Optional<U>&, T>,
368 std::is_convertible<const Optional<U>&, T>,
369 std::is_convertible<Optional<U>&&, T>,
370 std::is_convertible<const Optional<U>&&, T>>;
372 template <typename T, typename U>
373 using IsAssignableFromOptional =
374 disjunction<IsConvertibleFromOptional<T, U>,
375 std::is_assignable<T&, Optional<U>&>,
376 std::is_assignable<T&, const Optional<U>&>,
377 std::is_assignable<T&, Optional<U>&&>,
378 std::is_assignable<T&, const Optional<U>&&>>;
380 // Forward compatibility for C++17.
381 // Introduce one more deeper nested namespace to avoid leaking using std::swap.
382 namespace swappable_impl {
385 struct IsSwappableImpl {
386 // Tests if swap can be called. Check<T&>(0) returns true_type iff swap
387 // is available for T. Otherwise, Check's overload resolution falls back
388 // to Check(...) declared below thanks to SFINAE, so returns false_type.
389 template <typename T>
390 static auto Check(int)
391 -> decltype(swap(std::declval<T>(), std::declval<T>()), std::true_type());
393 template <typename T>
394 static std::false_type Check(...);
396 } // namespace swappable_impl
398 template <typename T>
399 struct IsSwappable : decltype(swappable_impl::IsSwappableImpl::Check<T&>(0)) {};
401 // Forward compatibility for C++20.
402 template <typename T>
403 using RemoveCvRefT = std::remove_cv_t<std::remove_reference_t<T>>;
405 } // namespace internal
407 // On Windows, by default, empty-base class optimization does not work,
408 // which means even if the base class is empty struct, it still consumes one
409 // byte for its body. __declspec(empty_bases) enables the optimization.
411 // https://blogs.msdn.microsoft.com/vcblog/2016/03/30/optimizing-the-layout-of-empty-base-classes-in-vs2015-update-2-3/
413 #define OPTIONAL_DECLSPEC_EMPTY_BASES __declspec(empty_bases)
415 #define OPTIONAL_DECLSPEC_EMPTY_BASES
418 // base::Optional is a Chromium version of the C++17 optional class:
419 // std::optional documentation:
420 // http://en.cppreference.com/w/cpp/utility/optional
421 // Chromium documentation:
422 // https://chromium.googlesource.com/chromium/src/+/master/docs/optional.md
424 // These are the differences between the specification and the implementation:
425 // - Constructors do not use 'constexpr' as it is a C++14 extension.
426 // - 'constexpr' might be missing in some places for reasons specified locally.
427 // - No exceptions are thrown, because they are banned from Chromium.
428 // Marked noexcept for only move constructor and move assign operators.
429 // - All the non-members are in the 'base' namespace instead of 'std'.
431 // Note that T cannot have a constructor T(Optional<T>) etc. Optional<T> checks
432 // T's constructor (specifically via IsConvertibleFromOptional), and in the
433 // check whether T can be constructible from Optional<T>, which is recursive
434 // so it does not work. As of Feb 2018, std::optional C++17 implementation in
435 // both clang and gcc has same limitation. MSVC SFINAE looks to have different
436 // behavior, but anyway it reports an error, too.
437 template <typename T>
438 class OPTIONAL_DECLSPEC_EMPTY_BASES Optional
439 : public internal::OptionalBase<T>,
440 public internal::CopyConstructible<std::is_copy_constructible<T>::value>,
441 public internal::MoveConstructible<std::is_move_constructible<T>::value>,
442 public internal::CopyAssignable<std::is_copy_constructible<T>::value &&
443 std::is_copy_assignable<T>::value>,
444 public internal::MoveAssignable<std::is_move_constructible<T>::value &&
445 std::is_move_assignable<T>::value> {
447 // Disable some versions of T that are ill-formed.
448 // See: https://timsong-cpp.github.io/cppwp/n4659/optional#syn-1
450 !std::is_same<internal::RemoveCvRefT<T>, in_place_t>::value,
451 "instantiation of base::Optional with in_place_t is ill-formed");
452 static_assert(!std::is_same<internal::RemoveCvRefT<T>, nullopt_t>::value,
453 "instantiation of base::Optional with nullopt_t is ill-formed");
455 !std::is_reference<T>::value,
456 "instantiation of base::Optional with a reference type is ill-formed");
457 // See: https://timsong-cpp.github.io/cppwp/n4659/optional#optional-3
458 static_assert(std::is_destructible<T>::value,
459 "instantiation of base::Optional with a non-destructible type "
461 // Arrays are explicitly disallowed because for arrays of known bound
462 // is_destructible is of undefined value.
463 // See: https://en.cppreference.com/w/cpp/types/is_destructible
465 !std::is_array<T>::value,
466 "instantiation of base::Optional with an array type is ill-formed");
469 #undef OPTIONAL_DECLSPEC_EMPTY_BASES
470 using value_type = T;
472 // Defer default/copy/move constructor implementation to OptionalBase.
473 constexpr Optional() = default;
474 constexpr Optional(const Optional& other) = default;
475 constexpr Optional(Optional&& other) noexcept(
476 std::is_nothrow_move_constructible<T>::value) = default;
478 constexpr Optional(nullopt_t) {} // NOLINT(runtime/explicit)
480 // Converting copy constructor. "explicit" only if
481 // std::is_convertible<const U&, T>::value is false. It is implemented by
482 // declaring two almost same constructors, but that condition in enable_if_t
483 // is different, so that either one is chosen, thanks to SFINAE.
486 std::enable_if_t<std::is_constructible<T, const U&>::value &&
487 !internal::IsConvertibleFromOptional<T, U>::value &&
488 std::is_convertible<const U&, T>::value,
490 Optional(const Optional<U>& other) : internal::OptionalBase<T>(other) {}
494 std::enable_if_t<std::is_constructible<T, const U&>::value &&
495 !internal::IsConvertibleFromOptional<T, U>::value &&
496 !std::is_convertible<const U&, T>::value,
498 explicit Optional(const Optional<U>& other)
499 : internal::OptionalBase<T>(other) {}
501 // Converting move constructor. Similar to converting copy constructor,
502 // declaring two (explicit and non-explicit) constructors.
505 std::enable_if_t<std::is_constructible<T, U&&>::value &&
506 !internal::IsConvertibleFromOptional<T, U>::value &&
507 std::is_convertible<U&&, T>::value,
509 Optional(Optional<U>&& other) : internal::OptionalBase<T>(std::move(other)) {}
513 std::enable_if_t<std::is_constructible<T, U&&>::value &&
514 !internal::IsConvertibleFromOptional<T, U>::value &&
515 !std::is_convertible<U&&, T>::value,
517 explicit Optional(Optional<U>&& other)
518 : internal::OptionalBase<T>(std::move(other)) {}
520 template <class... Args>
521 constexpr explicit Optional(in_place_t, Args&&... args)
522 : internal::OptionalBase<T>(in_place, std::forward<Args>(args)...) {}
527 class = std::enable_if_t<std::is_constructible<value_type,
528 std::initializer_list<U>&,
530 constexpr explicit Optional(in_place_t,
531 std::initializer_list<U> il,
533 : internal::OptionalBase<T>(in_place, il, std::forward<Args>(args)...) {}
535 // Forward value constructor. Similar to converting constructors,
536 // conditionally explicit.
538 typename U = value_type,
540 std::is_constructible<T, U&&>::value &&
541 !std::is_same<internal::RemoveCvRefT<U>, in_place_t>::value &&
542 !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
543 std::is_convertible<U&&, T>::value,
545 constexpr Optional(U&& value)
546 : internal::OptionalBase<T>(in_place, std::forward<U>(value)) {}
549 typename U = value_type,
551 std::is_constructible<T, U&&>::value &&
552 !std::is_same<internal::RemoveCvRefT<U>, in_place_t>::value &&
553 !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
554 !std::is_convertible<U&&, T>::value,
556 constexpr explicit Optional(U&& value)
557 : internal::OptionalBase<T>(in_place, std::forward<U>(value)) {}
559 ~Optional() = default;
561 // Defer copy-/move- assign operator implementation to OptionalBase.
562 Optional& operator=(const Optional& other) = default;
563 Optional& operator=(Optional&& other) noexcept(
564 std::is_nothrow_move_assignable<T>::value&&
565 std::is_nothrow_move_constructible<T>::value) = default;
567 Optional& operator=(nullopt_t) {
572 // Perfect-forwarded assignment.
573 template <typename U>
575 !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
576 std::is_constructible<T, U>::value &&
577 std::is_assignable<T&, U>::value &&
578 (!std::is_scalar<T>::value ||
579 !std::is_same<std::decay_t<U>, T>::value),
581 operator=(U&& value) {
582 InitOrAssign(std::forward<U>(value));
586 // Copy assign the state of other.
587 template <typename U>
588 std::enable_if_t<!internal::IsAssignableFromOptional<T, U>::value &&
589 std::is_constructible<T, const U&>::value &&
590 std::is_assignable<T&, const U&>::value,
592 operator=(const Optional<U>& other) {
597 // Move assign the state of other.
598 template <typename U>
599 std::enable_if_t<!internal::IsAssignableFromOptional<T, U>::value &&
600 std::is_constructible<T, U>::value &&
601 std::is_assignable<T&, U>::value,
603 operator=(Optional<U>&& other) {
604 MoveAssign(std::move(other));
608 constexpr const T* operator->() const {
609 CHECK(storage_.is_populated_);
610 return &storage_.value_;
613 constexpr T* operator->() {
614 CHECK(storage_.is_populated_);
615 return &storage_.value_;
618 constexpr const T& operator*() const & {
619 CHECK(storage_.is_populated_);
620 return storage_.value_;
623 constexpr T& operator*() & {
624 CHECK(storage_.is_populated_);
625 return storage_.value_;
628 constexpr const T&& operator*() const && {
629 CHECK(storage_.is_populated_);
630 return std::move(storage_.value_);
633 constexpr T&& operator*() && {
634 CHECK(storage_.is_populated_);
635 return std::move(storage_.value_);
638 constexpr explicit operator bool() const { return storage_.is_populated_; }
640 constexpr bool has_value() const { return storage_.is_populated_; }
642 constexpr T& value() & {
643 CHECK(storage_.is_populated_);
644 return storage_.value_;
647 constexpr const T& value() const & {
648 CHECK(storage_.is_populated_);
649 return storage_.value_;
652 constexpr T&& value() && {
653 CHECK(storage_.is_populated_);
654 return std::move(storage_.value_);
657 constexpr const T&& value() const && {
658 CHECK(storage_.is_populated_);
659 return std::move(storage_.value_);
663 constexpr T value_or(U&& default_value) const& {
664 // TODO(mlamouri): add the following assert when possible:
665 // static_assert(std::is_copy_constructible<T>::value,
666 // "T must be copy constructible");
667 static_assert(std::is_convertible<U, T>::value,
668 "U must be convertible to T");
669 return storage_.is_populated_
671 : static_cast<T>(std::forward<U>(default_value));
675 constexpr T value_or(U&& default_value) && {
676 // TODO(mlamouri): add the following assert when possible:
677 // static_assert(std::is_move_constructible<T>::value,
678 // "T must be move constructible");
679 static_assert(std::is_convertible<U, T>::value,
680 "U must be convertible to T");
681 return storage_.is_populated_
682 ? std::move(storage_.value_)
683 : static_cast<T>(std::forward<U>(default_value));
686 void swap(Optional& other) {
687 if (!storage_.is_populated_ && !other.storage_.is_populated_)
690 if (storage_.is_populated_ != other.storage_.is_populated_) {
691 if (storage_.is_populated_) {
692 other.storage_.Init(std::move(storage_.value_));
695 storage_.Init(std::move(other.storage_.value_));
696 other.FreeIfNeeded();
701 DCHECK(storage_.is_populated_ && other.storage_.is_populated_);
703 swap(**this, *other);
706 void reset() { FreeIfNeeded(); }
708 template <class... Args>
709 T& emplace(Args&&... args) {
711 storage_.Init(std::forward<Args>(args)...);
712 return storage_.value_;
715 template <class U, class... Args>
717 std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value,
719 emplace(std::initializer_list<U> il, Args&&... args) {
721 storage_.Init(il, std::forward<Args>(args)...);
722 return storage_.value_;
726 // Accessing template base class's protected member needs explicit
727 // declaration to do so.
728 using internal::OptionalBase<T>::CopyAssign;
729 using internal::OptionalBase<T>::FreeIfNeeded;
730 using internal::OptionalBase<T>::InitOrAssign;
731 using internal::OptionalBase<T>::MoveAssign;
732 using internal::OptionalBase<T>::storage_;
735 // Here after defines comparation operators. The definition follows
736 // http://en.cppreference.com/w/cpp/utility/optional/operator_cmp
737 // while bool() casting is replaced by has_value() to meet the chromium
739 template <class T, class U>
740 constexpr bool operator==(const Optional<T>& lhs, const Optional<U>& rhs) {
741 if (lhs.has_value() != rhs.has_value())
743 if (!lhs.has_value())
748 template <class T, class U>
749 constexpr bool operator!=(const Optional<T>& lhs, const Optional<U>& rhs) {
750 if (lhs.has_value() != rhs.has_value())
752 if (!lhs.has_value())
757 template <class T, class U>
758 constexpr bool operator<(const Optional<T>& lhs, const Optional<U>& rhs) {
759 if (!rhs.has_value())
761 if (!lhs.has_value())
766 template <class T, class U>
767 constexpr bool operator<=(const Optional<T>& lhs, const Optional<U>& rhs) {
768 if (!lhs.has_value())
770 if (!rhs.has_value())
775 template <class T, class U>
776 constexpr bool operator>(const Optional<T>& lhs, const Optional<U>& rhs) {
777 if (!lhs.has_value())
779 if (!rhs.has_value())
784 template <class T, class U>
785 constexpr bool operator>=(const Optional<T>& lhs, const Optional<U>& rhs) {
786 if (!rhs.has_value())
788 if (!lhs.has_value())
794 constexpr bool operator==(const Optional<T>& opt, nullopt_t) {
799 constexpr bool operator==(nullopt_t, const Optional<T>& opt) {
804 constexpr bool operator!=(const Optional<T>& opt, nullopt_t) {
805 return opt.has_value();
809 constexpr bool operator!=(nullopt_t, const Optional<T>& opt) {
810 return opt.has_value();
814 constexpr bool operator<(const Optional<T>& opt, nullopt_t) {
819 constexpr bool operator<(nullopt_t, const Optional<T>& opt) {
820 return opt.has_value();
824 constexpr bool operator<=(const Optional<T>& opt, nullopt_t) {
829 constexpr bool operator<=(nullopt_t, const Optional<T>& opt) {
834 constexpr bool operator>(const Optional<T>& opt, nullopt_t) {
835 return opt.has_value();
839 constexpr bool operator>(nullopt_t, const Optional<T>& opt) {
844 constexpr bool operator>=(const Optional<T>& opt, nullopt_t) {
849 constexpr bool operator>=(nullopt_t, const Optional<T>& opt) {
853 template <class T, class U>
854 constexpr bool operator==(const Optional<T>& opt, const U& value) {
855 return opt.has_value() ? *opt == value : false;
858 template <class T, class U>
859 constexpr bool operator==(const U& value, const Optional<T>& opt) {
860 return opt.has_value() ? value == *opt : false;
863 template <class T, class U>
864 constexpr bool operator!=(const Optional<T>& opt, const U& value) {
865 return opt.has_value() ? *opt != value : true;
868 template <class T, class U>
869 constexpr bool operator!=(const U& value, const Optional<T>& opt) {
870 return opt.has_value() ? value != *opt : true;
873 template <class T, class U>
874 constexpr bool operator<(const Optional<T>& opt, const U& value) {
875 return opt.has_value() ? *opt < value : true;
878 template <class T, class U>
879 constexpr bool operator<(const U& value, const Optional<T>& opt) {
880 return opt.has_value() ? value < *opt : false;
883 template <class T, class U>
884 constexpr bool operator<=(const Optional<T>& opt, const U& value) {
885 return opt.has_value() ? *opt <= value : true;
888 template <class T, class U>
889 constexpr bool operator<=(const U& value, const Optional<T>& opt) {
890 return opt.has_value() ? value <= *opt : false;
893 template <class T, class U>
894 constexpr bool operator>(const Optional<T>& opt, const U& value) {
895 return opt.has_value() ? *opt > value : false;
898 template <class T, class U>
899 constexpr bool operator>(const U& value, const Optional<T>& opt) {
900 return opt.has_value() ? value > *opt : true;
903 template <class T, class U>
904 constexpr bool operator>=(const Optional<T>& opt, const U& value) {
905 return opt.has_value() ? *opt >= value : false;
908 template <class T, class U>
909 constexpr bool operator>=(const U& value, const Optional<T>& opt) {
910 return opt.has_value() ? value >= *opt : true;
914 constexpr Optional<std::decay_t<T>> make_optional(T&& value) {
915 return Optional<std::decay_t<T>>(std::forward<T>(value));
918 template <class T, class... Args>
919 constexpr Optional<T> make_optional(Args&&... args) {
920 return Optional<T>(in_place, std::forward<Args>(args)...);
923 template <class T, class U, class... Args>
924 constexpr Optional<T> make_optional(std::initializer_list<U> il,
926 return Optional<T>(in_place, il, std::forward<Args>(args)...);
929 // Partial specialization for a function template is not allowed. Also, it is
930 // not allowed to add overload function to std namespace, while it is allowed
931 // to specialize the template in std. Thus, swap() (kind of) overloading is
932 // defined in base namespace, instead.
934 std::enable_if_t<std::is_move_constructible<T>::value &&
935 internal::IsSwappable<T>::value>
936 swap(Optional<T>& lhs, Optional<T>& rhs) {
945 struct hash<base::Optional<T>> {
946 size_t operator()(const base::Optional<T>& opt) const {
947 return opt == base::nullopt ? 0 : std::hash<T>()(*opt);
953 #endif // BASE_OPTIONAL_H_