variant.h
Go to the documentation of this file.
1 // Copyright 2018 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 // variant.h
17 // -----------------------------------------------------------------------------
18 //
19 // This header file defines an `absl::variant` type for holding a type-safe
20 // value of some prescribed set of types (noted as alternative types), and
21 // associated functions for managing variants.
22 //
23 // The `absl::variant` type is a form of type-safe union. An `absl::variant`
24 // should always hold a value of one of its alternative types (except in the
25 // "valueless by exception state" -- see below). A default-constructed
26 // `absl::variant` will hold the value of its first alternative type, provided
27 // it is default-constructable.
28 //
29 // In exceptional cases due to error, an `absl::variant` can hold no
30 // value (known as a "valueless by exception" state), though this is not the
31 // norm.
32 //
33 // As with `absl::optional`, an `absl::variant` -- when it holds a value --
34 // allocates a value of that type directly within the `variant` itself; it
35 // cannot hold a reference, array, or the type `void`; it can, however, hold a
36 // pointer to externally managed memory.
37 //
38 // `absl::variant` is a C++11 compatible version of the C++17 `std::variant`
39 // abstraction and is designed to be a drop-in replacement for code compliant
40 // with C++17.
41 
42 #ifndef ABSL_TYPES_VARIANT_H_
43 #define ABSL_TYPES_VARIANT_H_
44 
45 #include "absl/base/config.h"
46 #include "absl/utility/utility.h"
47 
48 #ifdef ABSL_HAVE_STD_VARIANT
49 
50 #include <variant> // IWYU pragma: export
51 
52 namespace absl {
53 using std::bad_variant_access;
54 using std::get;
55 using std::get_if;
57 using std::monostate;
58 using std::variant;
59 using std::variant_alternative;
61 using std::variant_npos;
62 using std::variant_size;
63 using std::variant_size_v;
64 using std::visit;
65 } // namespace absl
66 
67 #else // ABSL_HAVE_STD_VARIANT
68 
69 #include <functional>
70 #include <new>
71 #include <type_traits>
72 #include <utility>
73 
74 #include "absl/base/macros.h"
75 #include "absl/base/port.h"
76 #include "absl/meta/type_traits.h"
78 
79 namespace absl {
80 
81 // -----------------------------------------------------------------------------
82 // absl::variant
83 // -----------------------------------------------------------------------------
84 //
85 // An `absl::variant` type is a form of type-safe union. An `absl::variant` --
86 // except in exceptional cases -- always holds a value of one of its alternative
87 // types.
88 //
89 // Example:
90 //
91 // // Construct a variant that holds either an integer or a std::string and
92 // // assign it to a std::string.
93 // absl::variant<int, std::string> v = std::string("abc");
94 //
95 // // A default-contructed variant will hold a value-initialized value of
96 // // the first alternative type.
97 // auto a = absl::variant<int, std::string>(); // Holds an int of value '0'.
98 //
99 // // variants are assignable.
100 //
101 // // copy assignment
102 // auto v1 = absl::variant<int, std::string>("abc");
103 // auto v2 = absl::variant<int, std::string>(10);
104 // v2 = v1; // copy assign
105 //
106 // // move assignment
107 // auto v1 = absl::variant<int, std::string>("abc");
108 // v1 = absl::variant<int, std::string>(10);
109 //
110 // // assignment through type conversion
111 // a = 128; // variant contains int
112 // a = "128"; // variant contains std::string
113 //
114 // An `absl::variant` holding a value of one of its alternative types `T` holds
115 // an allocation of `T` directly within the variant itself. An `absl::variant`
116 // is not allowed to allocate additional storage, such as dynamic memory, to
117 // allocate the contained value. The contained value shall be allocated in a
118 // region of the variant storage suitably aligned for all alternative types.
119 template <typename... Ts>
120 class variant;
121 
122 // swap()
123 //
124 // Swaps two `absl::variant` values. This function is equivalent to `v.swap(w)`
125 // where `v` and `w` are `absl::variant` types.
126 //
127 // Note that this function requires all alternative types to be both swappable
128 // and move-constructible, because any two variants may refer to either the same
129 // type (in which case, they will be swapped) or to two different types (in
130 // which case the values will need to be moved).
131 //
132 template <
133  typename... Ts,
136  type_traits_internal::IsSwappable<Ts>...>::value,
137  int> = 0>
138 void swap(variant<Ts...>& v, variant<Ts...>& w) noexcept(noexcept(v.swap(w))) {
139  v.swap(w);
140 }
141 
142 // variant_size
143 //
144 // Returns the number of alternative types available for a given `absl::variant`
145 // type as a compile-time constant expression. As this is a class template, it
146 // is not generally useful for accessing the number of alternative types of
147 // any given `absl::variant` instance.
148 //
149 // Example:
150 //
151 // auto a = absl::variant<int, std::string>;
152 // constexpr int num_types =
153 // absl::variant_size<absl::variant<int, std::string>>();
154 //
155 // // You can also use the member constant `value`.
156 // constexpr int num_types =
157 // absl::variant_size<absl::variant<int, std::string>>::value;
158 //
159 // // `absl::variant_size` is more valuable for use in generic code:
160 // template <typename Variant>
161 // constexpr bool IsVariantMultivalue() {
162 // return absl::variant_size<Variant>() > 1;
163 // }
164 //
165 // Note that the set of cv-qualified specializations of `variant_size` are
166 // provided to ensure that those specializations compile (especially when passed
167 // within template logic).
168 template <class T>
169 struct variant_size;
170 
171 template <class... Ts>
172 struct variant_size<variant<Ts...>>
173  : std::integral_constant<std::size_t, sizeof...(Ts)> {};
174 
175 // Specialization of `variant_size` for const qualified variants.
176 template <class T>
177 struct variant_size<const T> : variant_size<T>::type {};
178 
179 // Specialization of `variant_size` for volatile qualified variants.
180 template <class T>
181 struct variant_size<volatile T> : variant_size<T>::type {};
182 
183 // Specialization of `variant_size` for const volatile qualified variants.
184 template <class T>
185 struct variant_size<const volatile T> : variant_size<T>::type {};
186 
187 // variant_alternative
188 //
189 // Returns the alternative type for a given `absl::variant` at the passed
190 // index value as a compile-time constant expression. As this is a class
191 // template resulting in a type, it is not useful for access of the run-time
192 // value of any given `absl::variant` variable.
193 //
194 // Example:
195 //
196 // // The type of the 0th alternative is "int".
197 // using alternative_type_0
198 // = absl::variant_alternative<0, absl::variant<int, std::string>>::type;
199 //
200 // static_assert(std::is_same<alternative_type_0, int>::value, "");
201 //
202 // // `absl::variant_alternative` is more valuable for use in generic code:
203 // template <typename Variant>
204 // constexpr bool IsFirstElementTrivial() {
205 // return std::is_trivial_v<variant_alternative<0, Variant>::type>;
206 // }
207 //
208 // Note that the set of cv-qualified specializations of `variant_alternative`
209 // are provided to ensure that those specializations compile (especially when
210 // passed within template logic).
211 template <std::size_t I, class T>
212 struct variant_alternative;
213 
214 template <std::size_t I, class... Types>
215 struct variant_alternative<I, variant<Types...>> {
216  using type =
218 };
219 
220 // Specialization of `variant_alternative` for const qualified variants.
221 template <std::size_t I, class T>
222 struct variant_alternative<I, const T> {
223  using type = const typename variant_alternative<I, T>::type;
224 };
225 
226 // Specialization of `variant_alternative` for volatile qualified variants.
227 template <std::size_t I, class T>
228 struct variant_alternative<I, volatile T> {
229  using type = volatile typename variant_alternative<I, T>::type;
230 };
231 
232 // Specialization of `variant_alternative` for const volatile qualified
233 // variants.
234 template <std::size_t I, class T>
235 struct variant_alternative<I, const volatile T> {
236  using type = const volatile typename variant_alternative<I, T>::type;
237 };
238 
239 // Template type alias for variant_alternative<I, T>::type.
240 //
241 // Example:
242 //
243 // using alternative_type_0
244 // = absl::variant_alternative_t<0, absl::variant<int, std::string>>;
245 // static_assert(std::is_same<alternative_type_0, int>::value, "");
246 template <std::size_t I, class T>
248 
249 // holds_alternative()
250 //
251 // Checks whether the given variant currently holds a given alternative type,
252 // returning `true` if so.
253 //
254 // Example:
255 //
256 // absl::variant<int, std::string> foo = 42;
257 // if (absl::holds_alternative<int>(foo)) {
258 // std::cout << "The variant holds an integer";
259 // }
260 template <class T, class... Types>
261 constexpr bool holds_alternative(const variant<Types...>& v) noexcept {
262  static_assert(
264  0>::value != sizeof...(Types),
265  "The type T must occur exactly once in Types...");
266  return v.index() ==
268 }
269 
270 // get()
271 //
272 // Returns a reference to the value currently within a given variant, using
273 // either a unique alternative type amongst the variant's set of alternative
274 // types, or the variant's index value. Attempting to get a variant's value
275 // using a type that is not unique within the variant's set of alternative types
276 // is a compile-time error. If the index of the alternative being specified is
277 // different from the index of the alternative that is currently stored, throws
278 // `absl::bad_variant_access`.
279 //
280 // Example:
281 //
282 // auto a = absl::variant<int, std::string>;
283 //
284 // // Get the value by type (if unique).
285 // int i = absl::get<int>(a);
286 //
287 // auto b = absl::variant<int, int>;
288 //
289 // // Getting the value by a type that is not unique is ill-formed.
290 // int j = absl::get<int>(b); // Compile Error!
291 //
292 // // Getting value by index not ambiguous and allowed.
293 // int k = absl::get<1>(b);
294 
295 // Overload for getting a variant's lvalue by type.
296 template <class T, class... Types>
297 constexpr T& get(variant<Types...>& v) { // NOLINT
299  variant_internal::IndexOf<T, Types...>::value>(v);
300 }
301 
302 // Overload for getting a variant's rvalue by type.
303 // Note: `absl::move()` is required to allow use of constexpr in C++11.
304 template <class T, class... Types>
305 constexpr T&& get(variant<Types...>&& v) {
308 }
309 
310 // Overload for getting a variant's const lvalue by type.
311 template <class T, class... Types>
312 constexpr const T& get(const variant<Types...>& v) {
314  variant_internal::IndexOf<T, Types...>::value>(v);
315 }
316 
317 // Overload for getting a variant's const rvalue by type.
318 // Note: `absl::move()` is required to allow use of constexpr in C++11.
319 template <class T, class... Types>
320 constexpr const T&& get(const variant<Types...>&& v) {
323 }
324 
325 // Overload for getting a variant's lvalue by index.
326 template <std::size_t I, class... Types>
327 constexpr variant_alternative_t<I, variant<Types...>>& get(
328  variant<Types...>& v) { // NOLINT
329  return variant_internal::VariantCoreAccess::CheckedAccess<I>(v);
330 }
331 
332 // Overload for getting a variant's rvalue by index.
333 // Note: `absl::move()` is required to allow use of constexpr in C++11.
334 template <std::size_t I, class... Types>
335 constexpr variant_alternative_t<I, variant<Types...>>&& get(
336  variant<Types...>&& v) {
337  return variant_internal::VariantCoreAccess::CheckedAccess<I>(absl::move(v));
338 }
339 
340 // Overload for getting a variant's const lvalue by index.
341 template <std::size_t I, class... Types>
342 constexpr const variant_alternative_t<I, variant<Types...>>& get(
343  const variant<Types...>& v) {
344  return variant_internal::VariantCoreAccess::CheckedAccess<I>(v);
345 }
346 
347 // Overload for getting a variant's const rvalue by index.
348 // Note: `absl::move()` is required to allow use of constexpr in C++11.
349 template <std::size_t I, class... Types>
350 constexpr const variant_alternative_t<I, variant<Types...>>&& get(
351  const variant<Types...>&& v) {
352  return variant_internal::VariantCoreAccess::CheckedAccess<I>(absl::move(v));
353 }
354 
355 // get_if()
356 //
357 // Returns a pointer to the value currently stored within a given variant, if
358 // present, using either a unique alternative type amongst the variant's set of
359 // alternative types, or the variant's index value. If such a value does not
360 // exist, returns `nullptr`.
361 //
362 // As with `get`, attempting to get a variant's value using a type that is not
363 // unique within the variant's set of alternative types is a compile-time error.
364 
365 // Overload for getting a pointer to the value stored in the given variant by
366 // index.
367 template <std::size_t I, class... Types>
368 constexpr absl::add_pointer_t<variant_alternative_t<I, variant<Types...>>>
370  return (v != nullptr && v->index() == I)
371  ? std::addressof(
372  variant_internal::VariantCoreAccess::Access<I>(*v))
373  : nullptr;
374 }
375 
376 // Overload for getting a pointer to the const value stored in the given
377 // variant by index.
378 template <std::size_t I, class... Types>
379 constexpr absl::add_pointer_t<const variant_alternative_t<I, variant<Types...>>>
380 get_if(const variant<Types...>* v) noexcept {
381  return (v != nullptr && v->index() == I)
382  ? std::addressof(
383  variant_internal::VariantCoreAccess::Access<I>(*v))
384  : nullptr;
385 }
386 
387 // Overload for getting a pointer to the value stored in the given variant by
388 // type.
389 template <class T, class... Types>
391  return absl::get_if<variant_internal::IndexOf<T, Types...>::value>(v);
392 }
393 
394 // Overload for getting a pointer to the const value stored in the given variant
395 // by type.
396 template <class T, class... Types>
398  const variant<Types...>* v) noexcept {
399  return absl::get_if<variant_internal::IndexOf<T, Types...>::value>(v);
400 }
401 
402 // visit()
403 //
404 // Calls a provided functor on a given set of variants. `absl::visit()` is
405 // commonly used to conditionally inspect the state of a given variant (or set
406 // of variants).
407 //
408 // The functor must return the same type when called with any of the variants'
409 // alternatives.
410 //
411 // Example:
412 //
413 // // Define a visitor functor
414 // struct GetVariant {
415 // template<typename T>
416 // void operator()(const T& i) const {
417 // std::cout << "The variant's value is: " << i;
418 // }
419 // };
420 //
421 // // Declare our variant, and call `absl::visit()` on it.
422 // // Note that `GetVariant()` returns void in either case.
423 // absl::variant<int, std::string> foo = std::string("foo");
424 // GetVariant visitor;
425 // absl::visit(visitor, foo); // Prints `The variant's value is: foo'
426 template <typename Visitor, typename... Variants>
427 variant_internal::VisitResult<Visitor, Variants...> visit(Visitor&& vis,
428  Variants&&... vars) {
429  return variant_internal::
431  variant_internal::PerformVisitation<Visitor, Variants...>{
432  std::forward_as_tuple(absl::forward<Variants>(vars)...),
433  absl::forward<Visitor>(vis)},
434  vars.index()...);
435 }
436 
437 // monostate
438 //
439 // The monostate class serves as a first alternative type for a variant for
440 // which the first variant type is otherwise not default-constructible.
441 struct monostate {};
442 
443 // `absl::monostate` Relational Operators
444 
445 constexpr bool operator<(monostate, monostate) noexcept { return false; }
446 constexpr bool operator>(monostate, monostate) noexcept { return false; }
447 constexpr bool operator<=(monostate, monostate) noexcept { return true; }
448 constexpr bool operator>=(monostate, monostate) noexcept { return true; }
449 constexpr bool operator==(monostate, monostate) noexcept { return true; }
450 constexpr bool operator!=(monostate, monostate) noexcept { return false; }
451 
452 
453 //------------------------------------------------------------------------------
454 // `absl::variant` Template Definition
455 //------------------------------------------------------------------------------
456 template <typename T0, typename... Tn>
457 class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> {
458  static_assert(absl::conjunction<std::is_object<T0>,
459  std::is_object<Tn>...>::value,
460  "Attempted to instantiate a variant containing a non-object "
461  "type.");
462  // Intentionally not qualifying `negation` with `absl::` to work around a bug
463  // in MSVC 2015 with inline namespace and variadic template.
464  static_assert(absl::conjunction<negation<std::is_array<T0> >,
465  negation<std::is_array<Tn> >...>::value,
466  "Attempted to instantiate a variant containing an array type.");
467  static_assert(absl::conjunction<std::is_nothrow_destructible<T0>,
468  std::is_nothrow_destructible<Tn>...>::value,
469  "Attempted to instantiate a variant containing a non-nothrow "
470  "destructible type.");
471 
473 
474  private:
475  using Base = variant_internal::VariantBase<T0, Tn...>;
476 
477  public:
478  // Constructors
479 
480  // Constructs a variant holding a default-initialized value of the first
481  // alternative type.
482  constexpr variant() /*noexcept(see 111above)*/ = default;
483 
484  // Copy constructor, standard semantics
485  variant(const variant& other) = default;
486 
487  // Move constructor, standard semantics
488  variant(variant&& other) /*noexcept(see above)*/ = default;
489 
490  // Constructs a variant of an alternative type specified by overload
491  // resolution of the provided forwarding arguments through
492  // direct-initialization.
493  //
494  // Note: If the selected constructor is a constexpr constructor, this
495  // constructor shall be a constexpr constructor.
496  //
497  // NOTE: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0608r1.html
498  // has been voted passed the design phase in the C++ standard meeting in Mar
499  // 2018. It will be implemented and integrated into `absl::variant`.
500  template <
501  class T,
502  std::size_t I = std::enable_if<
508  nullptr>
509  constexpr variant(T&& t) noexcept(std::is_nothrow_constructible<Tj, T>::value)
510  : Base(variant_internal::EmplaceTag<I>(), absl::forward<T>(t)) {}
511 
512  // Constructs a variant of an alternative type from the arguments through
513  // direct-initialization.
514  //
515  // Note: If the selected constructor is a constexpr constructor, this
516  // constructor shall be a constexpr constructor.
517  template <class T, class... Args,
518  typename std::enable_if<std::is_constructible<
520  Args...>::value>::type* = nullptr>
521  constexpr explicit variant(in_place_type_t<T>, Args&&... args)
522  : Base(variant_internal::EmplaceTag<
523  variant_internal::UnambiguousIndexOf<variant, T>::value>(),
524  absl::forward<Args>(args)...) {}
525 
526  // Constructs a variant of an alternative type from an initializer list
527  // and other arguments through direct-initialization.
528  //
529  // Note: If the selected constructor is a constexpr constructor, this
530  // constructor shall be a constexpr constructor.
531  template <class T, class U, class... Args,
532  typename std::enable_if<std::is_constructible<
533  variant_internal::UnambiguousTypeOfT<variant, T>,
534  std::initializer_list<U>&, Args...>::value>::type* = nullptr>
535  constexpr explicit variant(in_place_type_t<T>, std::initializer_list<U> il,
536  Args&&... args)
537  : Base(variant_internal::EmplaceTag<
538  variant_internal::UnambiguousIndexOf<variant, T>::value>(),
539  il, absl::forward<Args>(args)...) {}
540 
541  // Constructs a variant of an alternative type from a provided index,
542  // through value-initialization using the provided forwarded arguments.
543  template <std::size_t I, class... Args,
544  typename std::enable_if<std::is_constructible<
546  Args...>::value>::type* = nullptr>
547  constexpr explicit variant(in_place_index_t<I>, Args&&... args)
548  : Base(variant_internal::EmplaceTag<I>(), absl::forward<Args>(args)...) {}
549 
550  // Constructs a variant of an alternative type from a provided index,
551  // through value-initialization of an initializer list and the provided
552  // forwarded arguments.
553  template <std::size_t I, class U, class... Args,
554  typename std::enable_if<std::is_constructible<
555  variant_internal::VariantAlternativeSfinaeT<I, variant>,
556  std::initializer_list<U>&, Args...>::value>::type* = nullptr>
557  constexpr explicit variant(in_place_index_t<I>, std::initializer_list<U> il,
558  Args&&... args)
559  : Base(variant_internal::EmplaceTag<I>(), il,
560  absl::forward<Args>(args)...) {}
561 
562  // Destructors
563 
564  // Destroys the variant's currently contained value, provided that
565  // `absl::valueless_by_exception()` is false.
566  ~variant() = default;
567 
568  // Assignment Operators
569 
570  // Copy assignment operator
571  variant& operator=(const variant& other) = default;
572 
573  // Move assignment operator
574  variant& operator=(variant&& other) /*noexcept(see above)*/ = default;
575 
576  // Converting assignment operator
577  //
578  // NOTE: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0608r1.html
579  // has been voted passed the design phase in the C++ standard meeting in Mar
580  // 2018. It will be implemented and integrated into `absl::variant`.
581  template <
582  class T,
583  std::size_t I = std::enable_if<
584  !std::is_same<absl::decay_t<T>, variant>::value,
589  nullptr>
590  variant& operator=(T&& t) noexcept(
591  std::is_nothrow_assignable<Tj&, T>::value&&
592  std::is_nothrow_constructible<Tj, T>::value) {
593  variant_internal::VisitIndices<sizeof...(Tn) + 1>::Run(
595  this, absl::forward<T>(t)),
596  index());
597 
598  return *this;
599  }
600 
601 
602  // emplace() Functions
603 
604  // Constructs a value of the given alternative type T within the variant.
605  //
606  // Example:
607  //
608  // absl::variant<std::vector<int>, int, std::string> v;
609  // v.emplace<int>(99);
610  // v.emplace<std::string>("abc");
611  template <
612  class T, class... Args,
613  typename std::enable_if<std::is_constructible<
616  Args...>::value>::type* = nullptr>
617  T& emplace(Args&&... args) {
619  variant_internal::UnambiguousIndexOf<variant, T>::value>(
620  this, absl::forward<Args>(args)...);
621  }
622 
623  // Constructs a value of the given alternative type T within the variant using
624  // an initializer list.
625  //
626  // Example:
627  //
628  // absl::variant<std::vector<int>, int, std::string> v;
629  // v.emplace<std::vector<int>>({0, 1, 2});
630  template <
631  class T, class U, class... Args,
632  typename std::enable_if<std::is_constructible<
634  variant_internal::UnambiguousIndexOf<variant, T>::value, variant>,
635  std::initializer_list<U>&, Args...>::value>::type* = nullptr>
636  T& emplace(std::initializer_list<U> il, Args&&... args) {
638  variant_internal::UnambiguousIndexOf<variant, T>::value>(
639  this, il, absl::forward<Args>(args)...);
640  }
641 
642  // Destroys the current value of the variant (provided that
643  // `absl::valueless_by_exception()` is false, and constructs a new value at
644  // the given index.
645  //
646  // Example:
647  //
648  // absl::variant<std::vector<int>, int, int> v;
649  // v.emplace<1>(99);
650  // v.emplace<2>(98);
651  // v.emplace<int>(99); // Won't compile. 'int' isn't a unique type.
652  template <std::size_t I, class... Args,
653  typename std::enable_if<
654  std::is_constructible<absl::variant_alternative_t<I, variant>,
655  Args...>::value>::type* = nullptr>
657  return variant_internal::VariantCoreAccess::Replace<I>(
658  this, absl::forward<Args>(args)...);
659  }
660 
661  // Destroys the current value of the variant (provided that
662  // `absl::valueless_by_exception()` is false, and constructs a new value at
663  // the given index using an initializer list and the provided arguments.
664  //
665  // Example:
666  //
667  // absl::variant<std::vector<int>, int, int> v;
668  // v.emplace<0>({0, 1, 2});
669  template <std::size_t I, class U, class... Args,
670  typename std::enable_if<std::is_constructible<
672  std::initializer_list<U>&, Args...>::value>::type* = nullptr>
673  absl::variant_alternative_t<I, variant>& emplace(std::initializer_list<U> il,
674  Args&&... args) {
675  return variant_internal::VariantCoreAccess::Replace<I>(
676  this, il, absl::forward<Args>(args)...);
677  }
678 
679  // variant::valueless_by_exception()
680  //
681  // Returns false if and only if the variant currently holds a valid value.
682  constexpr bool valueless_by_exception() const noexcept {
683  return this->index_ == absl::variant_npos;
684  }
685 
686  // variant::index()
687  //
688  // Returns the index value of the variant's currently selected alternative
689  // type.
690  constexpr std::size_t index() const noexcept { return this->index_; }
691 
692  // variant::swap()
693  //
694  // Swaps the values of two variant objects.
695  //
696  void swap(variant& rhs) noexcept(
698  std::is_nothrow_move_constructible<T0>,
699  std::is_nothrow_move_constructible<Tn>...,
700  type_traits_internal::IsNothrowSwappable<T0>,
701  type_traits_internal::IsNothrowSwappable<Tn>...>::value) {
702  return variant_internal::VisitIndices<sizeof...(Tn) + 1>::Run(
703  variant_internal::Swap<T0, Tn...>{this, &rhs}, rhs.index());
704  }
705 };
706 
707 // We need a valid declaration of variant<> for SFINAE and overload resolution
708 // to work properly above, but we don't need a full declaration since this type
709 // will never be constructed. This declaration, though incomplete, suffices.
710 template <>
711 class variant<>;
712 
713 //------------------------------------------------------------------------------
714 // Relational Operators
715 //------------------------------------------------------------------------------
716 //
717 // If neither operand is in the `variant::valueless_by_exception` state:
718 //
719 // * If the index of both variants is the same, the relational operator
720 // returns the result of the corresponding relational operator for the
721 // corresponding alternative type.
722 // * If the index of both variants is not the same, the relational operator
723 // returns the result of that operation applied to the value of the left
724 // operand's index and the value of the right operand's index.
725 // * If at least one operand is in the valueless_by_exception state:
726 // - A variant in the valueless_by_exception state is only considered equal
727 // to another variant in the valueless_by_exception state.
728 // - If exactly one operand is in the valueless_by_exception state, the
729 // variant in the valueless_by_exception state is less than the variant
730 // that is not in the valueless_by_exception state.
731 //
732 // Note: The value 1 is added to each index in the relational comparisons such
733 // that the index corresponding to the valueless_by_exception state wraps around
734 // to 0 (the lowest value for the index type), and the remaining indices stay in
735 // the same relative order.
736 
737 // Equal-to operator
738 template <typename... Types>
739 constexpr variant_internal::RequireAllHaveEqualT<Types...> operator==(
740  const variant<Types...>& a, const variant<Types...>& b) {
741  return (a.index() == b.index()) &&
742  variant_internal::VisitIndices<sizeof...(Types)>::Run(
743  variant_internal::EqualsOp<Types...>{&a, &b}, a.index());
744 }
745 
746 // Not equal operator
747 template <typename... Types>
748 constexpr variant_internal::RequireAllHaveNotEqualT<Types...> operator!=(
749  const variant<Types...>& a, const variant<Types...>& b) {
750  return (a.index() != b.index()) ||
751  variant_internal::VisitIndices<sizeof...(Types)>::Run(
752  variant_internal::NotEqualsOp<Types...>{&a, &b}, a.index());
753 }
754 
755 // Less-than operator
756 template <typename... Types>
757 constexpr variant_internal::RequireAllHaveLessThanT<Types...> operator<(
758  const variant<Types...>& a, const variant<Types...>& b) {
759  return (a.index() != b.index())
760  ? (a.index() + 1) < (b.index() + 1)
761  : variant_internal::VisitIndices<sizeof...(Types)>::Run(
762  variant_internal::LessThanOp<Types...>{&a, &b}, a.index());
763 }
764 
765 // Greater-than operator
766 template <typename... Types>
767 constexpr variant_internal::RequireAllHaveGreaterThanT<Types...> operator>(
768  const variant<Types...>& a, const variant<Types...>& b) {
769  return (a.index() != b.index())
770  ? (a.index() + 1) > (b.index() + 1)
771  : variant_internal::VisitIndices<sizeof...(Types)>::Run(
772  variant_internal::GreaterThanOp<Types...>{&a, &b},
773  a.index());
774 }
775 
776 // Less-than or equal-to operator
777 template <typename... Types>
778 constexpr variant_internal::RequireAllHaveLessThanOrEqualT<Types...> operator<=(
779  const variant<Types...>& a, const variant<Types...>& b) {
780  return (a.index() != b.index())
781  ? (a.index() + 1) < (b.index() + 1)
782  : variant_internal::VisitIndices<sizeof...(Types)>::Run(
783  variant_internal::LessThanOrEqualsOp<Types...>{&a, &b},
784  a.index());
785 }
786 
787 // Greater-than or equal-to operator
788 template <typename... Types>
789 constexpr variant_internal::RequireAllHaveGreaterThanOrEqualT<Types...>
791  return (a.index() != b.index())
792  ? (a.index() + 1) > (b.index() + 1)
793  : variant_internal::VisitIndices<sizeof...(Types)>::Run(
794  variant_internal::GreaterThanOrEqualsOp<Types...>{&a, &b},
795  a.index());
796 }
797 
798 } // namespace absl
799 
800 namespace std {
801 
802 // hash()
803 template <> // NOLINT
804 struct hash<absl::monostate> {
805  std::size_t operator()(absl::monostate) const { return 0; }
806 };
807 
808 template <class... T> // NOLINT
809 struct hash<absl::variant<T...>>
810  : absl::variant_internal::VariantHashBase<absl::variant<T...>, void,
811  absl::remove_const_t<T>...> {};
812 
813 } // namespace std
814 
815 #endif // ABSL_HAVE_STD_VARIANT
816 
817 namespace absl {
818 namespace variant_internal {
819 
820 // Helper visitor for converting a variant<Ts...>` into another type (mostly
821 // variant) that can be constructed from any type.
822 template <typename To>
824  template <typename T>
825  To operator()(T&& v) const {
826  return To(std::forward<T>(v));
827  }
828 };
829 
830 } // namespace variant_internal
831 
832 // ConvertVariantTo()
833 //
834 // Helper functions to convert an `absl::variant` to a variant of another set of
835 // types, provided that the alternative type of the new variant type can be
836 // converted from any type in the source variant.
837 //
838 // Example:
839 //
840 // absl::variant<name1, name2, float> InternalReq(const Req&);
841 //
842 // // name1 and name2 are convertible to name
843 // absl::variant<name, float> ExternalReq(const Req& req) {
844 // return absl::ConvertVariantTo<absl::variant<name, float>>(
845 // InternalReq(req));
846 // }
847 template <typename To, typename Variant>
848 To ConvertVariantTo(Variant&& variant) {
850  std::forward<Variant>(variant));
851 }
852 
853 } // namespace absl
854 
855 #endif // ABSL_TYPES_VARIANT_H_
int v
Definition: variant_test.cc:81
typename variant_alternative< I, T >::type variant_alternative_t
Definition: variant.h:247
constexpr absl::add_pointer_t< variant_alternative_t< I, variant< Types... > > > get_if(variant< Types... > *v) noexcept
Definition: variant.h:369
constexpr bool valueless_by_exception() const noexcept
Definition: variant.h:682
const typename variant_alternative< I, T >::type type
Definition: variant.h:223
constexpr T && forward(absl::remove_reference_t< T > &t) noexcept
Definition: utility.h:228
bool operator<(const absl::InlinedVector< T, N, A > &a, const absl::InlinedVector< T, N, A > &b)
constexpr std::size_t index() const noexcept
Definition: variant.h:690
constexpr variant(T &&t) noexcept(std::is_nothrow_constructible< Tj, T >::value)
Definition: variant.h:509
variant_internal::VariantBase< T0, Tn... > Base
Definition: variant.h:475
static VariantAccessResult< I, Variant > CheckedAccess(Variant &&self)
UnambiguousTypeOfImpl< T, UnambiguousIndexOf< Variant, T >::value > UnambiguousTypeOfT
static ConversionAssignVisitor< Left, QualifiedNew > MakeConversionAssignVisitor(Left *left, QualifiedNew &&qual)
variant_internal::VariantAlternativeSfinaeT< I, variant< Types... >> type
Definition: variant.h:217
typename std::add_pointer< T >::type add_pointer_t
Definition: type_traits.h:525
typename std::decay< T >::type decay_t
Definition: type_traits.h:544
std::size_t operator()(absl::monostate) const
Definition: variant.h:805
To ConvertVariantTo(Variant &&variant)
Definition: variant.h:848
constexpr absl::add_pointer_t< const T > get_if(const variant< Types... > *v) noexcept
Definition: variant.h:397
typename VariantAlternativeSfinae< I, T >::type VariantAlternativeSfinaeT
constexpr variant(in_place_type_t< T >, Args &&...args)
Definition: variant.h:521
void(*)(utility_internal::InPlaceTypeTag< T >) in_place_type_t
Definition: utility.h:189
Definition: algorithm.h:29
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
T & emplace(std::initializer_list< U > il, Args &&...args)
Definition: variant.h:636
constexpr variant(in_place_type_t< T >, std::initializer_list< U > il, Args &&...args)
Definition: variant.h:535
bool operator==(const absl::InlinedVector< T, N, A > &a, const absl::InlinedVector< T, N, A > &b)
static absl::variant_alternative< NewIndex, Self >::type & Replace(Self *self, Args &&...args)
bool operator>=(const absl::InlinedVector< T, N, A > &a, const absl::InlinedVector< T, N, A > &b)
size_t value
bool operator!=(const absl::InlinedVector< T, N, A > &a, const absl::InlinedVector< T, N, A > &b)
variant & operator=(T &&t) noexcept(std::is_nothrow_assignable< Tj &, T >::value &&std::is_nothrow_constructible< Tj, T >::value)
Definition: variant.h:590
hash_default_hash< typename T::first_type > hash
void swap(absl::InlinedVector< T, N, A > &a, absl::InlinedVector< T, N, A > &b) noexcept(noexcept(a.swap(b)))
volatile typename variant_alternative< I, T >::type type
Definition: variant.h:229
void swap(variant &rhs) noexcept(absl::conjunction< std::is_nothrow_move_constructible< T0 >, std::is_nothrow_move_constructible< Tn >..., type_traits_internal::IsNothrowSwappable< T0 >, type_traits_internal::IsNothrowSwappable< Tn >... >::value)
Definition: variant.h:696
T & emplace(Args &&...args)
Definition: variant.h:617
const volatile typename variant_alternative< I, T >::type type
Definition: variant.h:236
void(*)(utility_internal::InPlaceIndexTag< I >) in_place_index_t
Definition: utility.h:206
constexpr variant(in_place_index_t< I >, Args &&...args)
Definition: variant.h:547
variant_internal::VisitResult< Visitor, Variants... > visit(Visitor &&vis, Variants &&...vars)
Definition: variant.h:427
absl::variant_alternative_t< I, variant > & emplace(std::initializer_list< U > il, Args &&...args)
Definition: variant.h:673
absl::string_view get(const Cont &c)
uint64_t b
Definition: layout_test.cc:50
absl::variant_alternative_t< I, variant > & emplace(Args &&...args)
Definition: variant.h:656
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: utility.h:219
constexpr variant(in_place_index_t< I >, std::initializer_list< U > il, Args &&...args)
Definition: variant.h:557
typename IndexOfMeta< Expected, Types... >::type IndexOf
constexpr bool holds_alternative(const variant< Types... > &v) noexcept
Definition: variant.h:261
bool operator<=(const absl::InlinedVector< T, N, A > &a, const absl::InlinedVector< T, N, A > &b)


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:19:58