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