optional.h
Go to the documentation of this file.
1 // Copyright 2017 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // -----------------------------------------------------------------------------
16 // optional.h
17 // -----------------------------------------------------------------------------
18 //
19 // This header file defines the `absl::optional` type for holding a value which
20 // may or may not be present. This type is useful for providing value semantics
21 // for operations that may either wish to return or hold "something-or-nothing".
22 //
23 // Example:
24 //
25 // // A common way to signal operation failure is to provide an output
26 // // parameter and a bool return type:
27 // bool AcquireResource(const Input&, Resource * out);
28 //
29 // // Providing an absl::optional return type provides a cleaner API:
30 // absl::optional<Resource> AcquireResource(const Input&);
31 //
32 // `absl::optional` is a C++11 compatible version of the C++17 `std::optional`
33 // abstraction and is designed to be a drop-in replacement for code compliant
34 // with C++17.
35 #ifndef ABSL_TYPES_OPTIONAL_H_
36 #define ABSL_TYPES_OPTIONAL_H_
37 
38 #include "absl/base/config.h" // TODO(calabrese) IWYU removal?
39 #include "absl/utility/utility.h"
40 
41 #ifdef ABSL_HAVE_STD_OPTIONAL
42 
43 #include <optional> // IWYU pragma: export
44 
45 namespace absl {
46 using std::bad_optional_access;
47 using std::optional;
48 using std::make_optional;
49 using std::nullopt_t;
50 using std::nullopt;
51 } // namespace absl
52 
53 #else // ABSL_HAVE_STD_OPTIONAL
54 
55 #include <cassert>
56 #include <functional>
57 #include <initializer_list>
58 #include <type_traits>
59 #include <utility>
60 
61 #include "absl/base/attributes.h"
63 #include "absl/meta/type_traits.h"
66 
67 namespace absl {
68 
69 // nullopt_t
70 //
71 // Class type for `absl::nullopt` used to indicate an `absl::optional<T>` type
72 // that does not contain a value.
73 struct nullopt_t {
74  // It must not be default-constructible to avoid ambiguity for opt = {}.
75  explicit constexpr nullopt_t(optional_internal::init_t) noexcept {}
76 };
77 
78 // nullopt
79 //
80 // A tag constant of type `absl::nullopt_t` used to indicate an empty
81 // `absl::optional` in certain functions, such as construction or assignment.
84 
85 // -----------------------------------------------------------------------------
86 // absl::optional
87 // -----------------------------------------------------------------------------
88 //
89 // A value of type `absl::optional<T>` holds either a value of `T` or an
90 // "empty" value. When it holds a value of `T`, it stores it as a direct
91 // sub-object, so `sizeof(optional<T>)` is approximately
92 // `sizeof(T) + sizeof(bool)`.
93 //
94 // This implementation is based on the specification in the latest draft of the
95 // C++17 `std::optional` specification as of May 2017, section 20.6.
96 //
97 // Differences between `absl::optional<T>` and `std::optional<T>` include:
98 //
99 // * `constexpr` is not used for non-const member functions.
100 // (dependency on some differences between C++11 and C++14.)
101 // * `absl::nullopt` and `absl::in_place` are not declared `constexpr`. We
102 // need the inline variable support in C++17 for external linkage.
103 // * Throws `absl::bad_optional_access` instead of
104 // `std::bad_optional_access`.
105 // * `make_optional()` cannot be declared `constexpr` due to the absence of
106 // guaranteed copy elision.
107 // * The move constructor's `noexcept` specification is stronger, i.e. if the
108 // default allocator is non-throwing (via setting
109 // `ABSL_ALLOCATOR_NOTHROW`), it evaluates to `noexcept(true)`, because
110 // we assume
111 // a) move constructors should only throw due to allocation failure and
112 // b) if T's move constructor allocates, it uses the same allocation
113 // function as the default allocator.
114 //
115 template <typename T>
116 class optional : private optional_internal::optional_data<T>,
118  optional_internal::ctor_copy_traits<T>::traits>,
120  optional_internal::assign_copy_traits<T>::traits> {
122 
123  public:
124  typedef T value_type;
125 
126  // Constructors
127 
128  // Constructs an `optional` holding an empty value, NOT a default constructed
129  // `T`.
130  constexpr optional() noexcept {}
131 
132  // Constructs an `optional` initialized with `nullopt` to hold an empty value.
133  constexpr optional(nullopt_t) noexcept {} // NOLINT(runtime/explicit)
134 
135  // Copy constructor, standard semantics
136  optional(const optional& src) = default;
137 
138  // Move constructor, standard semantics
139  optional(optional&& src) = default;
140 
141  // Constructs a non-empty `optional` direct-initialized value of type `T` from
142  // the arguments `std::forward<Args>(args)...` within the `optional`.
143  // (The `in_place_t` is a tag used to indicate that the contained object
144  // should be constructed in-place.)
145  template <typename InPlaceT, typename... Args,
147  std::is_same<InPlaceT, in_place_t>,
148  std::is_constructible<T, Args&&...> >::value>* = nullptr>
149  constexpr explicit optional(InPlaceT, Args&&... args)
150  : data_base(in_place_t(), absl::forward<Args>(args)...) {}
151 
152  // Constructs a non-empty `optional` direct-initialized value of type `T` from
153  // the arguments of an initializer_list and `std::forward<Args>(args)...`.
154  // (The `in_place_t` is a tag used to indicate that the contained object
155  // should be constructed in-place.)
156  template <typename U, typename... Args,
157  typename = typename std::enable_if<std::is_constructible<
158  T, std::initializer_list<U>&, Args&&...>::value>::type>
159  constexpr explicit optional(in_place_t, std::initializer_list<U> il,
160  Args&&... args)
161  : data_base(in_place_t(), il, absl::forward<Args>(args)...) {
162  }
163 
164  // Value constructor (implicit)
165  template <
166  typename U = T,
167  typename std::enable_if<
168  absl::conjunction<absl::negation<std::is_same<
169  in_place_t, typename std::decay<U>::type> >,
170  absl::negation<std::is_same<
171  optional<T>, typename std::decay<U>::type> >,
172  std::is_convertible<U&&, T>,
173  std::is_constructible<T, U&&> >::value,
174  bool>::type = false>
175  constexpr optional(U&& v) : data_base(in_place_t(), absl::forward<U>(v)) {}
176 
177  // Value constructor (explicit)
178  template <
179  typename U = T,
180  typename std::enable_if<
181  absl::conjunction<absl::negation<std::is_same<
182  in_place_t, typename std::decay<U>::type>>,
183  absl::negation<std::is_same<
184  optional<T>, typename std::decay<U>::type>>,
186  std::is_constructible<T, U&&>>::value,
187  bool>::type = false>
188  explicit constexpr optional(U&& v)
189  : data_base(in_place_t(), absl::forward<U>(v)) {}
190 
191  // Converting copy constructor (implicit)
192  template <typename U,
193  typename std::enable_if<
196  std::is_constructible<T, const U&>,
198  optional_internal::
199  is_constructible_convertible_from_optional<T, U> >,
200  std::is_convertible<const U&, T> >::value,
201  bool>::type = false>
202  optional(const optional<U>& rhs) {
203  if (rhs) {
204  this->construct(*rhs);
205  }
206  }
207 
208  // Converting copy constructor (explicit)
209  template <typename U,
210  typename std::enable_if<
212  absl::negation<std::is_same<T, U>>,
213  std::is_constructible<T, const U&>,
215  optional_internal::
216  is_constructible_convertible_from_optional<T, U>>,
218  bool>::type = false>
219  explicit optional(const optional<U>& rhs) {
220  if (rhs) {
221  this->construct(*rhs);
222  }
223  }
224 
225  // Converting move constructor (implicit)
226  template <typename U,
227  typename std::enable_if<
229  absl::negation<std::is_same<T, U> >,
230  std::is_constructible<T, U&&>,
232  optional_internal::
233  is_constructible_convertible_from_optional<T, U> >,
234  std::is_convertible<U&&, T> >::value,
235  bool>::type = false>
237  if (rhs) {
238  this->construct(std::move(*rhs));
239  }
240  }
241 
242  // Converting move constructor (explicit)
243  template <
244  typename U,
245  typename std::enable_if<
247  absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
250  T, U>>,
251  absl::negation<std::is_convertible<U&&, T>>>::value,
252  bool>::type = false>
253  explicit optional(optional<U>&& rhs) {
254  if (rhs) {
255  this->construct(std::move(*rhs));
256  }
257  }
258 
259  // Destructor. Trivial if `T` is trivially destructible.
260  ~optional() = default;
261 
262  // Assignment Operators
263 
264  // Assignment from `nullopt`
265  //
266  // Example:
267  //
268  // struct S { int value; };
269  // optional<S> opt = absl::nullopt; // Could also use opt = { };
271  this->destruct();
272  return *this;
273  }
274 
275  // Copy assignment operator, standard semantics
276  optional& operator=(const optional& src) = default;
277 
278  // Move assignment operator, standard semantics
279  optional& operator=(optional&& src) = default;
280 
281  // Value assignment operators
282  template <
283  typename U = T,
284  typename = typename std::enable_if<absl::conjunction<
286  std::is_same<optional<T>, typename std::decay<U>::type>>,
289  std::is_same<T, typename std::decay<U>::type>>>,
290  std::is_constructible<T, U>, std::is_assignable<T&, U>>::value>::type>
292  this->assign(std::forward<U>(v));
293  return *this;
294  }
295 
296  template <
297  typename U,
298  typename = typename std::enable_if<absl::conjunction<
299  absl::negation<std::is_same<T, U>>,
300  std::is_constructible<T, const U&>, std::is_assignable<T&, const U&>,
302  optional_internal::
303  is_constructible_convertible_assignable_from_optional<
304  T, U>>>::value>::type>
306  if (rhs) {
307  this->assign(*rhs);
308  } else {
309  this->destruct();
310  }
311  return *this;
312  }
313 
314  template <typename U,
315  typename = typename std::enable_if<absl::conjunction<
316  absl::negation<std::is_same<T, U>>, std::is_constructible<T, U>,
317  std::is_assignable<T&, U>,
319  optional_internal::
320  is_constructible_convertible_assignable_from_optional<
321  T, U>>>::value>::type>
323  if (rhs) {
324  this->assign(std::move(*rhs));
325  } else {
326  this->destruct();
327  }
328  return *this;
329  }
330 
331  // Modifiers
332 
333  // optional::reset()
334  //
335  // Destroys the inner `T` value of an `absl::optional` if one is present.
336  ABSL_ATTRIBUTE_REINITIALIZES void reset() noexcept { this->destruct(); }
337 
338  // optional::emplace()
339  //
340  // (Re)constructs the underlying `T` in-place with the given forwarded
341  // arguments.
342  //
343  // Example:
344  //
345  // optional<Foo> opt;
346  // opt.emplace(arg1,arg2,arg3); // Constructs Foo(arg1,arg2,arg3)
347  //
348  // If the optional is non-empty, and the `args` refer to subobjects of the
349  // current object, then behaviour is undefined, because the current object
350  // will be destructed before the new object is constructed with `args`.
351  template <typename... Args,
352  typename = typename std::enable_if<
353  std::is_constructible<T, Args&&...>::value>::type>
354  T& emplace(Args&&... args) {
355  this->destruct();
356  this->construct(std::forward<Args>(args)...);
357  return reference();
358  }
359 
360  // Emplace reconstruction overload for an initializer list and the given
361  // forwarded arguments.
362  //
363  // Example:
364  //
365  // struct Foo {
366  // Foo(std::initializer_list<int>);
367  // };
368  //
369  // optional<Foo> opt;
370  // opt.emplace({1,2,3}); // Constructs Foo({1,2,3})
371  template <typename U, typename... Args,
372  typename = typename std::enable_if<std::is_constructible<
373  T, std::initializer_list<U>&, Args&&...>::value>::type>
374  T& emplace(std::initializer_list<U> il, Args&&... args) {
375  this->destruct();
376  this->construct(il, std::forward<Args>(args)...);
377  return reference();
378  }
379 
380  // Swaps
381 
382  // Swap, standard semantics
383  void swap(optional& rhs) noexcept(
386  if (*this) {
387  if (rhs) {
388  type_traits_internal::Swap(**this, *rhs);
389  } else {
390  rhs.construct(std::move(**this));
391  this->destruct();
392  }
393  } else {
394  if (rhs) {
395  this->construct(std::move(*rhs));
396  rhs.destruct();
397  } else {
398  // No effect (swap(disengaged, disengaged)).
399  }
400  }
401  }
402 
403  // Observers
404 
405  // optional::operator->()
406  //
407  // Accesses the underlying `T` value's member `m` of an `optional`. If the
408  // `optional` is empty, behavior is undefined.
409  //
410  // If you need myOpt->foo in constexpr, use (*myOpt).foo instead.
411  const T* operator->() const {
412  assert(this->engaged_);
413  return std::addressof(this->data_);
414  }
415  T* operator->() {
416  assert(this->engaged_);
417  return std::addressof(this->data_);
418  }
419 
420  // optional::operator*()
421  //
422  // Accesses the underlying `T` value of an `optional`. If the `optional` is
423  // empty, behavior is undefined.
424  constexpr const T& operator*() const& {
425  return ABSL_ASSERT(this->engaged_), reference();
426  }
427  T& operator*() & {
428  assert(this->engaged_);
429  return reference();
430  }
431  constexpr const T&& operator*() const && {
432  return absl::move(reference());
433  }
434  T&& operator*() && {
435  assert(this->engaged_);
436  return std::move(reference());
437  }
438 
439  // optional::operator bool()
440  //
441  // Returns false if and only if the `optional` is empty.
442  //
443  // if (opt) {
444  // // do something with opt.value();
445  // } else {
446  // // opt is empty.
447  // }
448  //
449  constexpr explicit operator bool() const noexcept { return this->engaged_; }
450 
451  // optional::has_value()
452  //
453  // Determines whether the `optional` contains a value. Returns `false` if and
454  // only if `*this` is empty.
455  constexpr bool has_value() const noexcept { return this->engaged_; }
456 
457 // Suppress bogus warning on MSVC: MSVC complains call to reference() after
458 // throw_bad_optional_access() is unreachable.
459 #ifdef _MSC_VER
460 #pragma warning(push)
461 #pragma warning(disable : 4702)
462 #endif // _MSC_VER
463  // optional::value()
464  //
465  // Returns a reference to an `optional`s underlying value. The constness
466  // and lvalue/rvalue-ness of the `optional` is preserved to the view of
467  // the `T` sub-object. Throws `absl::bad_optional_access` when the `optional`
468  // is empty.
469  constexpr const T& value() const & {
470  return static_cast<bool>(*this)
471  ? reference()
473  }
474  T& value() & {
475  return static_cast<bool>(*this)
476  ? reference()
478  }
479  T&& value() && { // NOLINT(build/c++11)
480  return std::move(
481  static_cast<bool>(*this)
482  ? reference()
484  }
485  constexpr const T&& value() const && { // NOLINT(build/c++11)
486  return absl::move(
487  static_cast<bool>(*this)
488  ? reference()
490  }
491 #ifdef _MSC_VER
492 #pragma warning(pop)
493 #endif // _MSC_VER
494 
495  // optional::value_or()
496  //
497  // Returns either the value of `T` or a passed default `v` if the `optional`
498  // is empty.
499  template <typename U>
500  constexpr T value_or(U&& v) const& {
502  "optional<T>::value_or: T must by copy constructible");
504  "optional<T>::value_or: U must be convertible to T");
505  return static_cast<bool>(*this)
506  ? **this
507  : static_cast<T>(absl::forward<U>(v));
508  }
509  template <typename U>
510  T value_or(U&& v) && { // NOLINT(build/c++11)
512  "optional<T>::value_or: T must by move constructible");
514  "optional<T>::value_or: U must be convertible to T");
515  return static_cast<bool>(*this) ? std::move(**this)
516  : static_cast<T>(std::forward<U>(v));
517  }
518 
519  private:
520  // Private accessors for internal storage viewed as reference to T.
521  constexpr const T& reference() const { return this->data_; }
522  T& reference() { return this->data_; }
523 
524  // T constraint checks. You can't have an optional of nullopt_t, in_place_t
525  // or a reference.
526  static_assert(
527  !std::is_same<nullopt_t, typename std::remove_cv<T>::type>::value,
528  "optional<nullopt_t> is not allowed.");
529  static_assert(
530  !std::is_same<in_place_t, typename std::remove_cv<T>::type>::value,
531  "optional<in_place_t> is not allowed.");
532  static_assert(!std::is_reference<T>::value,
533  "optional<reference> is not allowed.");
534 };
535 
536 // Non-member functions
537 
538 // swap()
539 //
540 // Performs a swap between two `absl::optional` objects, using standard
541 // semantics.
542 template <typename T, typename std::enable_if<
545  bool>::type = false>
546 void swap(optional<T>& a, optional<T>& b) noexcept(noexcept(a.swap(b))) {
547  a.swap(b);
548 }
549 
550 // make_optional()
551 //
552 // Creates a non-empty `optional<T>` where the type of `T` is deduced. An
553 // `absl::optional` can also be explicitly instantiated with
554 // `make_optional<T>(v)`.
555 //
556 // Note: `make_optional()` constructions may be declared `constexpr` for
557 // trivially copyable types `T`. Non-trivial types require copy elision
558 // support in C++17 for `make_optional` to support `constexpr` on such
559 // non-trivial types.
560 //
561 // Example:
562 //
563 // constexpr absl::optional<int> opt = absl::make_optional(1);
564 // static_assert(opt.value() == 1, "");
565 template <typename T>
567  return optional<typename std::decay<T>::type>(absl::forward<T>(v));
568 }
569 
570 template <typename T, typename... Args>
571 constexpr optional<T> make_optional(Args&&... args) {
572  return optional<T>(in_place_t(), absl::forward<Args>(args)...);
573 }
574 
575 template <typename T, typename U, typename... Args>
576 constexpr optional<T> make_optional(std::initializer_list<U> il,
577  Args&&... args) {
578  return optional<T>(in_place_t(), il,
579  absl::forward<Args>(args)...);
580 }
581 
582 // Relational operators [optional.relops]
583 
584 // Empty optionals are considered equal to each other and less than non-empty
585 // optionals. Supports relations between optional<T> and optional<U>, between
586 // optional<T> and U, and between optional<T> and nullopt.
587 //
588 // Note: We're careful to support T having non-bool relationals.
589 
590 // Requires: The expression, e.g. "*x == *y" shall be well-formed and its result
591 // shall be convertible to bool.
592 // The C++17 (N4606) "Returns:" statements are translated into
593 // code in an obvious way here, and the original text retained as function docs.
594 // Returns: If bool(x) != bool(y), false; otherwise if bool(x) == false, true;
595 // otherwise *x == *y.
596 template <typename T, typename U>
597 constexpr auto operator==(const optional<T>& x, const optional<U>& y)
598  -> decltype(optional_internal::convertible_to_bool(*x == *y)) {
599  return static_cast<bool>(x) != static_cast<bool>(y)
600  ? false
601  : static_cast<bool>(x) == false ? true
602  : static_cast<bool>(*x == *y);
603 }
604 
605 // Returns: If bool(x) != bool(y), true; otherwise, if bool(x) == false, false;
606 // otherwise *x != *y.
607 template <typename T, typename U>
608 constexpr auto operator!=(const optional<T>& x, const optional<U>& y)
609  -> decltype(optional_internal::convertible_to_bool(*x != *y)) {
610  return static_cast<bool>(x) != static_cast<bool>(y)
611  ? true
612  : static_cast<bool>(x) == false ? false
613  : static_cast<bool>(*x != *y);
614 }
615 // Returns: If !y, false; otherwise, if !x, true; otherwise *x < *y.
616 template <typename T, typename U>
617 constexpr auto operator<(const optional<T>& x, const optional<U>& y)
618  -> decltype(optional_internal::convertible_to_bool(*x < *y)) {
619  return !y ? false : !x ? true : static_cast<bool>(*x < *y);
620 }
621 // Returns: If !x, false; otherwise, if !y, true; otherwise *x > *y.
622 template <typename T, typename U>
623 constexpr auto operator>(const optional<T>& x, const optional<U>& y)
624  -> decltype(optional_internal::convertible_to_bool(*x > *y)) {
625  return !x ? false : !y ? true : static_cast<bool>(*x > *y);
626 }
627 // Returns: If !x, true; otherwise, if !y, false; otherwise *x <= *y.
628 template <typename T, typename U>
629 constexpr auto operator<=(const optional<T>& x, const optional<U>& y)
630  -> decltype(optional_internal::convertible_to_bool(*x <= *y)) {
631  return !x ? true : !y ? false : static_cast<bool>(*x <= *y);
632 }
633 // Returns: If !y, true; otherwise, if !x, false; otherwise *x >= *y.
634 template <typename T, typename U>
635 constexpr auto operator>=(const optional<T>& x, const optional<U>& y)
636  -> decltype(optional_internal::convertible_to_bool(*x >= *y)) {
637  return !y ? true : !x ? false : static_cast<bool>(*x >= *y);
638 }
639 
640 // Comparison with nullopt [optional.nullops]
641 // The C++17 (N4606) "Returns:" statements are used directly here.
642 template <typename T>
643 constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept {
644  return !x;
645 }
646 template <typename T>
647 constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept {
648  return !x;
649 }
650 template <typename T>
651 constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept {
652  return static_cast<bool>(x);
653 }
654 template <typename T>
655 constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept {
656  return static_cast<bool>(x);
657 }
658 template <typename T>
659 constexpr bool operator<(const optional<T>&, nullopt_t) noexcept {
660  return false;
661 }
662 template <typename T>
663 constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept {
664  return static_cast<bool>(x);
665 }
666 template <typename T>
667 constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept {
668  return !x;
669 }
670 template <typename T>
671 constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept {
672  return true;
673 }
674 template <typename T>
675 constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept {
676  return static_cast<bool>(x);
677 }
678 template <typename T>
679 constexpr bool operator>(nullopt_t, const optional<T>&) noexcept {
680  return false;
681 }
682 template <typename T>
683 constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept {
684  return true;
685 }
686 template <typename T>
687 constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept {
688  return !x;
689 }
690 
691 // Comparison with T [optional.comp_with_t]
692 
693 // Requires: The expression, e.g. "*x == v" shall be well-formed and its result
694 // shall be convertible to bool.
695 // The C++17 (N4606) "Equivalent to:" statements are used directly here.
696 template <typename T, typename U>
697 constexpr auto operator==(const optional<T>& x, const U& v)
698  -> decltype(optional_internal::convertible_to_bool(*x == v)) {
699  return static_cast<bool>(x) ? static_cast<bool>(*x == v) : false;
700 }
701 template <typename T, typename U>
702 constexpr auto operator==(const U& v, const optional<T>& x)
703  -> decltype(optional_internal::convertible_to_bool(v == *x)) {
704  return static_cast<bool>(x) ? static_cast<bool>(v == *x) : false;
705 }
706 template <typename T, typename U>
707 constexpr auto operator!=(const optional<T>& x, const U& v)
708  -> decltype(optional_internal::convertible_to_bool(*x != v)) {
709  return static_cast<bool>(x) ? static_cast<bool>(*x != v) : true;
710 }
711 template <typename T, typename U>
712 constexpr auto operator!=(const U& v, const optional<T>& x)
713  -> decltype(optional_internal::convertible_to_bool(v != *x)) {
714  return static_cast<bool>(x) ? static_cast<bool>(v != *x) : true;
715 }
716 template <typename T, typename U>
717 constexpr auto operator<(const optional<T>& x, const U& v)
718  -> decltype(optional_internal::convertible_to_bool(*x < v)) {
719  return static_cast<bool>(x) ? static_cast<bool>(*x < v) : true;
720 }
721 template <typename T, typename U>
722 constexpr auto operator<(const U& v, const optional<T>& x)
723  -> decltype(optional_internal::convertible_to_bool(v < *x)) {
724  return static_cast<bool>(x) ? static_cast<bool>(v < *x) : false;
725 }
726 template <typename T, typename U>
727 constexpr auto operator<=(const optional<T>& x, const U& v)
728  -> decltype(optional_internal::convertible_to_bool(*x <= v)) {
729  return static_cast<bool>(x) ? static_cast<bool>(*x <= v) : true;
730 }
731 template <typename T, typename U>
732 constexpr auto operator<=(const U& v, const optional<T>& x)
733  -> decltype(optional_internal::convertible_to_bool(v <= *x)) {
734  return static_cast<bool>(x) ? static_cast<bool>(v <= *x) : false;
735 }
736 template <typename T, typename U>
737 constexpr auto operator>(const optional<T>& x, const U& v)
738  -> decltype(optional_internal::convertible_to_bool(*x > v)) {
739  return static_cast<bool>(x) ? static_cast<bool>(*x > v) : false;
740 }
741 template <typename T, typename U>
742 constexpr auto operator>(const U& v, const optional<T>& x)
743  -> decltype(optional_internal::convertible_to_bool(v > *x)) {
744  return static_cast<bool>(x) ? static_cast<bool>(v > *x) : true;
745 }
746 template <typename T, typename U>
747 constexpr auto operator>=(const optional<T>& x, const U& v)
748  -> decltype(optional_internal::convertible_to_bool(*x >= v)) {
749  return static_cast<bool>(x) ? static_cast<bool>(*x >= v) : false;
750 }
751 template <typename T, typename U>
752 constexpr auto operator>=(const U& v, const optional<T>& x)
753  -> decltype(optional_internal::convertible_to_bool(v >= *x)) {
754  return static_cast<bool>(x) ? static_cast<bool>(v >= *x) : true;
755 }
756 
757 } // namespace absl
758 
759 namespace std {
760 
761 // std::hash specialization for absl::optional.
762 template <typename T>
763 struct hash<absl::optional<T> >
765 
766 } // namespace std
767 
768 #undef ABSL_MSVC_CONSTEXPR_BUG_IN_UNION_LIKE_CLASS
769 
770 #endif // ABSL_HAVE_STD_OPTIONAL
771 
772 #endif // ABSL_TYPES_OPTIONAL_H_
int v
Definition: variant_test.cc:81
constexpr optional(nullopt_t) noexcept
Definition: optional.h:133
constexpr nullopt_t(optional_internal::init_t) noexcept
Definition: optional.h:75
optional & operator=(const optional< U > &rhs)
Definition: optional.h:305
T && value() &&
Definition: optional.h:479
T & emplace(Args &&... args)
Definition: optional.h:354
T & value() &
Definition: optional.h:474
constexpr T && forward(absl::remove_reference_t< T > &t) noexcept
Definition: utility.h:228
optional & operator=(optional< U > &&rhs)
Definition: optional.h:322
#define ABSL_ATTRIBUTE_REINITIALIZES
Definition: attributes.h:535
#define ABSL_ASSERT(expr)
Definition: macros.h:198
T && operator*() &&
Definition: optional.h:434
T * operator->()
Definition: optional.h:415
T & emplace(std::initializer_list< U > il, Args &&... args)
Definition: optional.h:374
constexpr const T & operator*() const &
Definition: optional.h:424
optional(const optional< U > &rhs)
Definition: optional.h:202
Definition: algorithm.h:29
const T * operator->() const
Definition: optional.h:411
optional & operator=(nullopt_t) noexcept
Definition: optional.h:270
bool operator>(const absl::InlinedVector< T, N, A > &a, const absl::InlinedVector< T, N, A > &b)
typename std::enable_if< B, T >::type enable_if_t
Definition: type_traits.h:547
optional & operator=(U &&v)
Definition: optional.h:291
void swap(optional &rhs) noexcept(std::is_nothrow_move_constructible< T >::value &&type_traits_internal::IsNothrowSwappable< T >::value)
Definition: optional.h:383
T & reference()
Definition: optional.h:522
constexpr const T & reference() const
Definition: optional.h:521
bool operator==(const absl::InlinedVector< T, N, A > &a, const absl::InlinedVector< T, N, A > &b)
const char * data_
Definition: test_util.cc:98
constexpr optional() noexcept
Definition: optional.h:130
bool convertible_to_bool(bool)
bool operator>=(const absl::InlinedVector< T, N, A > &a, const absl::InlinedVector< T, N, A > &b)
void Swap(T &lhs, T &rhs) noexcept(IsNothrowSwappable< T >::value)
Definition: type_traits.h:673
size_t value
bool operator!=(const absl::InlinedVector< T, N, A > &a, const absl::InlinedVector< T, N, A > &b)
hash_default_hash< typename T::first_type > hash
constexpr optional(InPlaceT, Args &&... args)
Definition: optional.h:149
constexpr const T && operator*() const &&
Definition: optional.h:431
constexpr bool has_value() const noexcept
Definition: optional.h:455
void swap(absl::InlinedVector< T, N, A > &a, absl::InlinedVector< T, N, A > &b) noexcept(noexcept(a.swap(b)))
static std::function< void(void *, Slot *, Slot)> construct
constexpr const T & value() const &
Definition: optional.h:469
constexpr optional< T > make_optional(std::initializer_list< U > il, Args &&... args)
Definition: optional.h:576
constexpr optional< typename std::decay< T >::type > make_optional(T &&v)
Definition: optional.h:566
T & operator*() &
Definition: optional.h:427
constexpr const T && value() const &&
Definition: optional.h:485
ABSL_ATTRIBUTE_REINITIALIZES void reset() noexcept
Definition: optional.h:336
optional(optional< U > &&rhs)
Definition: optional.h:236
T value_or(U &&v) &&
Definition: optional.h:510
uint64_t b
Definition: layout_test.cc:50
constexpr optional(in_place_t, std::initializer_list< U > il, Args &&... args)
Definition: optional.h:159
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: utility.h:219
ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, -1)
constexpr T value_or(U &&v) const &
Definition: optional.h:500
constexpr optional(U &&v)
Definition: optional.h:175


abseil_cpp
Author(s):
autogenerated on Mon Feb 28 2022 21:31:19