internal/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 // Implementation details of absl/types/variant.h, pulled into a
16 // separate file to avoid cluttering the top of the API header with
17 // implementation details.
18 
19 #ifndef ABSL_TYPES_variant_internal_H_
20 #define ABSL_TYPES_variant_internal_H_
21 
22 #include <cassert>
23 #include <cstddef>
24 #include <cstdlib>
25 #include <memory>
26 #include <stdexcept>
27 #include <tuple>
28 #include <type_traits>
29 
30 #include "absl/base/config.h"
34 #include "absl/base/macros.h"
35 #include "absl/base/optimization.h"
36 #include "absl/meta/type_traits.h"
38 #include "absl/utility/utility.h"
39 
40 #if !defined(ABSL_HAVE_STD_VARIANT)
41 
42 namespace absl {
43 
44 template <class... Types>
45 class variant;
46 
47 ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, -1);
48 
49 template <class T>
50 struct variant_size;
51 
52 template <std::size_t I, class T>
54 
55 namespace variant_internal {
56 
57 // NOTE: See specializations below for details.
58 template <std::size_t I, class T>
60 
61 // Requires: I < variant_size_v<T>.
62 //
63 // Value: The Ith type of Types...
64 template <std::size_t I, class T0, class... Tn>
65 struct VariantAlternativeSfinae<I, variant<T0, Tn...>>
66  : VariantAlternativeSfinae<I - 1, variant<Tn...>> {};
67 
68 // Value: T0
69 template <class T0, class... Ts>
70 struct VariantAlternativeSfinae<0, variant<T0, Ts...>> {
71  using type = T0;
72 };
73 
74 template <std::size_t I, class T>
76 
77 // NOTE: Requires T to be a reference type.
78 template <class T, class U>
79 struct GiveQualsTo;
80 
81 template <class T, class U>
82 struct GiveQualsTo<T&, U> {
83  using type = U&;
84 };
85 
86 template <class T, class U>
87 struct GiveQualsTo<T&&, U> {
88  using type = U&&;
89 };
90 
91 template <class T, class U>
92 struct GiveQualsTo<const T&, U> {
93  using type = const U&;
94 };
95 
96 template <class T, class U>
97 struct GiveQualsTo<const T&&, U> {
98  using type = const U&&;
99 };
100 
101 template <class T, class U>
102 struct GiveQualsTo<volatile T&, U> {
103  using type = volatile U&;
104 };
105 
106 template <class T, class U>
107 struct GiveQualsTo<volatile T&&, U> {
108  using type = volatile U&&;
109 };
110 
111 template <class T, class U>
112 struct GiveQualsTo<volatile const T&, U> {
113  using type = volatile const U&;
114 };
115 
116 template <class T, class U>
117 struct GiveQualsTo<volatile const T&&, U> {
118  using type = volatile const U&&;
119 };
120 
121 template <class T, class U>
123 
124 // Convenience alias, since size_t integral_constant is used a lot in this file.
125 template <std::size_t I>
126 using SizeT = std::integral_constant<std::size_t, I>;
127 
129 
130 template <class Variant, class T, class = void>
132 
133 template <std::size_t I, class Variant>
135 
136 template <std::size_t I, template <class...> class Variantemplate, class... T>
137 struct VariantAccessResultImpl<I, Variantemplate<T...>&> {
138  using type = typename absl::variant_alternative<I, variant<T...>>::type&;
139 };
140 
141 template <std::size_t I, template <class...> class Variantemplate, class... T>
142 struct VariantAccessResultImpl<I, const Variantemplate<T...>&> {
143  using type =
144  const typename absl::variant_alternative<I, variant<T...>>::type&;
145 };
146 
147 template <std::size_t I, template <class...> class Variantemplate, class... T>
148 struct VariantAccessResultImpl<I, Variantemplate<T...>&&> {
149  using type = typename absl::variant_alternative<I, variant<T...>>::type&&;
150 };
151 
152 template <std::size_t I, template <class...> class Variantemplate, class... T>
153 struct VariantAccessResultImpl<I, const Variantemplate<T...>&&> {
154  using type =
155  const typename absl::variant_alternative<I, variant<T...>>::type&&;
156 };
157 
158 template <std::size_t I, class Variant>
159 using VariantAccessResult =
161 
162 // NOTE: This is used instead of std::array to reduce instantiation overhead.
163 template <class T, std::size_t Size>
164 struct SimpleArray {
165  static_assert(Size != 0, "");
166  T value[Size];
167 };
168 
169 template <class T>
170 struct AccessedType {
171  using type = T;
172 };
173 
174 template <class T>
176 
177 template <class T, std::size_t Size>
178 struct AccessedType<SimpleArray<T, Size>> {
180 };
181 
182 template <class T>
183 constexpr T AccessSimpleArray(const T& value) {
184  return value;
185 }
186 
187 template <class T, std::size_t Size, class... SizeT>
189  std::size_t head_index,
190  SizeT... tail_indices) {
191  return AccessSimpleArray(table.value[head_index], tail_indices...);
192 }
193 
194 // Note: Intentionally is an alias.
195 template <class T>
197 
198 template <class Op, class... Vs>
201 };
202 
203 template <class Op, class... Vs>
204 using VisitIndicesResultT = typename VisitIndicesResultImpl<Op, Vs...>::type;
205 
206 template <class ReturnType, class FunctionObject, class EndIndices,
207  std::size_t... BoundIndices>
209 
210 template <class ReturnType, class FunctionObject, std::size_t... Indices>
211 constexpr ReturnType call_with_indices(FunctionObject&& function) {
212  static_assert(
213  std::is_same<ReturnType, decltype(std::declval<FunctionObject>()(
214  SizeT<Indices>()...))>::value,
215  "Not all visitation overloads have the same return type.");
216  return absl::forward<FunctionObject>(function)(SizeT<Indices>()...);
217 }
218 
219 template <class ReturnType, class FunctionObject, std::size_t... BoundIndices>
220 struct MakeVisitationMatrix<ReturnType, FunctionObject, index_sequence<>,
221  BoundIndices...> {
222  using ResultType = ReturnType (*)(FunctionObject&&);
223  static constexpr ResultType Run() {
224  return &call_with_indices<ReturnType, FunctionObject,
225  (BoundIndices - 1)...>;
226  }
227 };
228 
229 template <class ReturnType, class FunctionObject, class EndIndices,
230  class CurrIndices, std::size_t... BoundIndices>
232 
233 template <class ReturnType, class FunctionObject, std::size_t... EndIndices,
234  std::size_t... CurrIndices, std::size_t... BoundIndices>
236  ReturnType, FunctionObject, index_sequence<EndIndices...>,
237  index_sequence<CurrIndices...>, BoundIndices...> {
238  using ResultType = SimpleArray<
239  typename MakeVisitationMatrix<ReturnType, FunctionObject,
240  index_sequence<EndIndices...>>::ResultType,
241  sizeof...(CurrIndices)>;
242 
243  static constexpr ResultType Run() {
244  return {{MakeVisitationMatrix<ReturnType, FunctionObject,
245  index_sequence<EndIndices...>,
246  BoundIndices..., CurrIndices>::Run()...}};
247  }
248 };
249 
250 template <class ReturnType, class FunctionObject, std::size_t HeadEndIndex,
251  std::size_t... TailEndIndices, std::size_t... BoundIndices>
252 struct MakeVisitationMatrix<ReturnType, FunctionObject,
253  index_sequence<HeadEndIndex, TailEndIndices...>,
254  BoundIndices...>
256  ReturnType, FunctionObject, index_sequence<TailEndIndices...>,
257  absl::make_index_sequence<HeadEndIndex>, BoundIndices...> {};
258 
260  template <class Op>
262  Op&& /*ignored*/) {
263 #if ABSL_HAVE_BUILTIN(__builtin_unreachable) || \
264  (defined(__GNUC__) && !defined(__clang__))
265  __builtin_unreachable();
266 #elif defined(_MSC_VER)
267  __assume(false);
268 #else
269  // Try to use assert of false being identified as an unreachable intrinsic.
270  // NOTE: We use assert directly to increase chances of exploiting an assume
271  // intrinsic.
272  assert(false); // NOLINT
273 
274  // Hack to silence potential no return warning -- cause an infinite loop.
275  return Run(absl::forward<Op>(op));
276 #endif // Checks for __builtin_unreachable
277  }
278 };
279 
280 template <class Op, std::size_t I>
283  return absl::base_internal::Invoke(absl::forward<Op>(op), SizeT<I>());
284  }
285 };
286 
287 // The number 33 is just a guess at a reasonable maximum to our switch. It is
288 // not based on any analysis. The reason it is a power of 2 plus 1 instead of a
289 // power of 2 is because the number was picked to correspond to a power of 2
290 // amount of "normal" alternatives, plus one for the possibility of the user
291 // providing "monostate" in addition to the more natural alternatives.
292 ABSL_INTERNAL_INLINE_CONSTEXPR(std::size_t, MaxUnrolledVisitCases, 33);
293 
294 // Note: The default-definition is for unreachable cases.
295 template <bool IsReachable>
296 struct PickCaseImpl {
297  template <class Op, std::size_t I>
299 };
300 
301 template <>
302 struct PickCaseImpl</*IsReachable =*/true> {
303  template <class Op, std::size_t I>
305 };
306 
307 // Note: This form of dance with template aliases is to make sure that we
308 // instantiate a number of templates proportional to the number of variant
309 // alternatives rather than a number of templates proportional to our
310 // maximum unrolled amount of visitation cases (aliases are effectively
311 // "free" whereas other template instantiations are costly).
312 template <class Op, std::size_t I, std::size_t EndIndex>
313 using PickCase = typename PickCaseImpl<(I < EndIndex)>::template Apply<Op, I>;
314 
315 template <class ReturnType>
316 [[noreturn]] ReturnType TypedThrowBadVariantAccess() {
318 }
319 
320 // Given N variant sizes, determine the number of cases there would need to be
321 // in a single switch-statement that would cover every possibility in the
322 // corresponding N-ary visit operation.
323 template <std::size_t... NumAlternatives>
325 
326 template <std::size_t HeadNumAlternatives, std::size_t... TailNumAlternatives>
327 struct NumCasesOfSwitch<HeadNumAlternatives, TailNumAlternatives...> {
328  static constexpr std::size_t value =
329  (HeadNumAlternatives + 1) *
331 };
332 
333 template <>
335  static constexpr std::size_t value = 1;
336 };
337 
338 // A switch statement optimizes better than the table of function pointers.
339 template <std::size_t EndIndex>
341  static_assert(EndIndex <= MaxUnrolledVisitCases,
342  "Maximum unrolled switch size exceeded.");
343 
344  template <class Op>
345  static VisitIndicesResultT<Op, std::size_t> Run(Op&& op, std::size_t i) {
346  switch (i) {
347  case 0:
348  return PickCase<Op, 0, EndIndex>::Run(absl::forward<Op>(op));
349  case 1:
350  return PickCase<Op, 1, EndIndex>::Run(absl::forward<Op>(op));
351  case 2:
352  return PickCase<Op, 2, EndIndex>::Run(absl::forward<Op>(op));
353  case 3:
354  return PickCase<Op, 3, EndIndex>::Run(absl::forward<Op>(op));
355  case 4:
356  return PickCase<Op, 4, EndIndex>::Run(absl::forward<Op>(op));
357  case 5:
358  return PickCase<Op, 5, EndIndex>::Run(absl::forward<Op>(op));
359  case 6:
360  return PickCase<Op, 6, EndIndex>::Run(absl::forward<Op>(op));
361  case 7:
362  return PickCase<Op, 7, EndIndex>::Run(absl::forward<Op>(op));
363  case 8:
364  return PickCase<Op, 8, EndIndex>::Run(absl::forward<Op>(op));
365  case 9:
366  return PickCase<Op, 9, EndIndex>::Run(absl::forward<Op>(op));
367  case 10:
368  return PickCase<Op, 10, EndIndex>::Run(absl::forward<Op>(op));
369  case 11:
370  return PickCase<Op, 11, EndIndex>::Run(absl::forward<Op>(op));
371  case 12:
372  return PickCase<Op, 12, EndIndex>::Run(absl::forward<Op>(op));
373  case 13:
374  return PickCase<Op, 13, EndIndex>::Run(absl::forward<Op>(op));
375  case 14:
376  return PickCase<Op, 14, EndIndex>::Run(absl::forward<Op>(op));
377  case 15:
378  return PickCase<Op, 15, EndIndex>::Run(absl::forward<Op>(op));
379  case 16:
380  return PickCase<Op, 16, EndIndex>::Run(absl::forward<Op>(op));
381  case 17:
382  return PickCase<Op, 17, EndIndex>::Run(absl::forward<Op>(op));
383  case 18:
384  return PickCase<Op, 18, EndIndex>::Run(absl::forward<Op>(op));
385  case 19:
386  return PickCase<Op, 19, EndIndex>::Run(absl::forward<Op>(op));
387  case 20:
388  return PickCase<Op, 20, EndIndex>::Run(absl::forward<Op>(op));
389  case 21:
390  return PickCase<Op, 21, EndIndex>::Run(absl::forward<Op>(op));
391  case 22:
392  return PickCase<Op, 22, EndIndex>::Run(absl::forward<Op>(op));
393  case 23:
394  return PickCase<Op, 23, EndIndex>::Run(absl::forward<Op>(op));
395  case 24:
396  return PickCase<Op, 24, EndIndex>::Run(absl::forward<Op>(op));
397  case 25:
398  return PickCase<Op, 25, EndIndex>::Run(absl::forward<Op>(op));
399  case 26:
400  return PickCase<Op, 26, EndIndex>::Run(absl::forward<Op>(op));
401  case 27:
402  return PickCase<Op, 27, EndIndex>::Run(absl::forward<Op>(op));
403  case 28:
404  return PickCase<Op, 28, EndIndex>::Run(absl::forward<Op>(op));
405  case 29:
406  return PickCase<Op, 29, EndIndex>::Run(absl::forward<Op>(op));
407  case 30:
408  return PickCase<Op, 30, EndIndex>::Run(absl::forward<Op>(op));
409  case 31:
410  return PickCase<Op, 31, EndIndex>::Run(absl::forward<Op>(op));
411  case 32:
412  return PickCase<Op, 32, EndIndex>::Run(absl::forward<Op>(op));
413  default:
414  ABSL_ASSERT(i == variant_npos);
415  return absl::base_internal::Invoke(absl::forward<Op>(op), NPos());
416  }
417  }
418 };
419 
420 template <std::size_t... EndIndices>
422  template <class Op, class... SizeT>
423  static VisitIndicesResultT<Op, SizeT...> Run(Op&& op, SizeT... indices) {
424  return AccessSimpleArray(
426  index_sequence<(EndIndices + 1)...>>::Run(),
427  (indices + 1)...)(absl::forward<Op>(op));
428  }
429 };
430 
431 // Take an N-dimensional series of indices and convert them into a single index
432 // without loss of information. The purpose of this is to be able to convert an
433 // N-ary visit operation into a single switch statement.
434 template <std::size_t...>
436 
437 template <std::size_t HeadSize, std::size_t... TailSize>
438 struct FlattenIndices<HeadSize, TailSize...> {
439  template<class... SizeType>
440  static constexpr std::size_t Run(std::size_t head, SizeType... tail) {
441  return head + HeadSize * FlattenIndices<TailSize...>::Run(tail...);
442  }
443 };
444 
445 template <>
446 struct FlattenIndices<> {
447  static constexpr std::size_t Run() { return 0; }
448 };
449 
450 // Take a single "flattened" index (flattened by FlattenIndices) and determine
451 // the value of the index of one of the logically represented dimensions.
452 template <std::size_t I, std::size_t IndexToGet, std::size_t HeadSize,
453  std::size_t... TailSize>
455  static constexpr std::size_t value =
456  UnflattenIndex<I / HeadSize, IndexToGet - 1, TailSize...>::value;
457 };
458 
459 template <std::size_t I, std::size_t HeadSize, std::size_t... TailSize>
460 struct UnflattenIndex<I, 0, HeadSize, TailSize...> {
461  static constexpr std::size_t value = (I % HeadSize);
462 };
463 
464 // The backend for converting an N-ary visit operation into a unary visit.
465 template <class IndexSequence, std::size_t... EndIndices>
467 
468 template <std::size_t... N, std::size_t... EndIndices>
469 struct VisitIndicesVariadicImpl<absl::index_sequence<N...>, EndIndices...> {
470  // A type that can take an N-ary function object and converts it to a unary
471  // function object that takes a single, flattened index, and "unflattens" it
472  // into its individual dimensions when forwarding to the wrapped object.
473  template <class Op>
474  struct FlattenedOp {
475  template <std::size_t I>
476  VisitIndicesResultT<Op, decltype(EndIndices)...> operator()(
477  SizeT<I> /*index*/) && {
478  return base_internal::Invoke(
479  absl::forward<Op>(op),
480  SizeT<UnflattenIndex<I, N, (EndIndices + 1)...>::value -
481  std::size_t{1}>()...);
482  }
483 
484  Op&& op;
485  };
486 
487  template <class Op, class... SizeType>
488  static VisitIndicesResultT<Op, decltype(EndIndices)...> Run(
489  Op&& op, SizeType... i) {
490  return VisitIndicesSwitch<NumCasesOfSwitch<EndIndices...>::value>::Run(
491  FlattenedOp<Op>{absl::forward<Op>(op)},
492  FlattenIndices<(EndIndices + std::size_t{1})...>::Run(
493  (i + std::size_t{1})...));
494  }
495 };
496 
497 template <std::size_t... EndIndices>
499  : VisitIndicesVariadicImpl<absl::make_index_sequence<sizeof...(EndIndices)>,
500  EndIndices...> {};
501 
502 // This implementation will flatten N-ary visit operations into a single switch
503 // statement when the number of cases would be less than our maximum specified
504 // switch-statement size.
505 // TODO(calabrese)
506 // Based on benchmarks, determine whether the function table approach actually
507 // does optimize better than a chain of switch statements and possibly update
508 // the implementation accordingly. Also consider increasing the maximum switch
509 // size.
510 template <std::size_t... EndIndices>
512  : absl::conditional_t<(NumCasesOfSwitch<EndIndices...>::value <=
513  MaxUnrolledVisitCases),
514  VisitIndicesVariadic<EndIndices...>,
515  VisitIndicesFallback<EndIndices...>> {};
516 
517 template <std::size_t EndIndex>
518 struct VisitIndices<EndIndex>
519  : absl::conditional_t<(EndIndex <= MaxUnrolledVisitCases),
520  VisitIndicesSwitch<EndIndex>,
521  VisitIndicesFallback<EndIndex>> {};
522 
523 // Suppress bogus warning on MSVC: MSVC complains that the `reinterpret_cast`
524 // below is returning the address of a temporary or local object.
525 #ifdef _MSC_VER
526 #pragma warning(push)
527 #pragma warning(disable : 4172)
528 #endif // _MSC_VER
529 
530 // TODO(calabrese) std::launder
531 // TODO(calabrese) constexpr
532 // NOTE: DO NOT REMOVE the `inline` keyword as it is necessary to work around a
533 // MSVC bug. See https://github.com/abseil/abseil-cpp/issues/129 for details.
534 template <class Self, std::size_t I>
535 inline VariantAccessResult<I, Self> AccessUnion(Self&& self, SizeT<I> /*i*/) {
536  return reinterpret_cast<VariantAccessResult<I, Self>>(self);
537 }
538 
539 #ifdef _MSC_VER
540 #pragma warning(pop)
541 #endif // _MSC_VER
542 
543 template <class T>
544 void DeducedDestroy(T& self) { // NOLINT
545  self.~T();
546 }
547 
548 // NOTE: This type exists as a single entity for variant and its bases to
549 // befriend. It contains helper functionality that manipulates the state of the
550 // variant, such as the implementation of things like assignment and emplace
551 // operations.
552 struct VariantCoreAccess {
553  template <class VariantType>
554  static typename VariantType::Variant& Derived(VariantType& self) { // NOLINT
555  return static_cast<typename VariantType::Variant&>(self);
556  }
557 
558  template <class VariantType>
559  static const typename VariantType::Variant& Derived(
560  const VariantType& self) { // NOLINT
561  return static_cast<const typename VariantType::Variant&>(self);
562  }
563 
564  template <class VariantType>
565  static void Destroy(VariantType& self) { // NOLINT
566  Derived(self).destroy();
567  self.index_ = absl::variant_npos;
568  }
569 
570  template <class Variant>
571  static void SetIndex(Variant& self, std::size_t i) { // NOLINT
572  self.index_ = i;
573  }
574 
575  template <class Variant>
576  static void InitFrom(Variant& self, Variant&& other) { // NOLINT
577  VisitIndices<absl::variant_size<Variant>::value>::Run(
578  InitFromVisitor<Variant, Variant&&>{&self,
579  std::forward<Variant>(other)},
580  other.index());
581  self.index_ = other.index();
582  }
583 
584  // Access a variant alternative, assuming the index is correct.
585  template <std::size_t I, class Variant>
586  static VariantAccessResult<I, Variant> Access(Variant&& self) {
587  // This cast instead of invocation of AccessUnion with an rvalue is a
588  // workaround for msvc. Without this there is a runtime failure when dealing
589  // with rvalues.
590  // TODO(calabrese) Reduce test case and find a simpler workaround.
591  return static_cast<VariantAccessResult<I, Variant>>(
592  variant_internal::AccessUnion(self.state_, SizeT<I>()));
593  }
594 
595  // Access a variant alternative, throwing if the index is incorrect.
596  template <std::size_t I, class Variant>
597  static VariantAccessResult<I, Variant> CheckedAccess(Variant&& self) {
598  if (ABSL_PREDICT_FALSE(self.index_ != I)) {
599  TypedThrowBadVariantAccess<VariantAccessResult<I, Variant>>();
600  }
601 
602  return Access<I>(absl::forward<Variant>(self));
603  }
604 
605  // The implementation of the move-assignment operation for a variant.
606  template <class VType>
607  struct MoveAssignVisitor {
608  using DerivedType = typename VType::Variant;
609  template <std::size_t NewIndex>
610  void operator()(SizeT<NewIndex> /*new_i*/) const {
611  if (left->index_ == NewIndex) {
612  Access<NewIndex>(*left) = std::move(Access<NewIndex>(*right));
613  } else {
614  Derived(*left).template emplace<NewIndex>(
615  std::move(Access<NewIndex>(*right)));
616  }
617  }
618 
619  void operator()(SizeT<absl::variant_npos> /*new_i*/) const {
620  Destroy(*left);
621  }
622 
623  VType* left;
624  VType* right;
625  };
626 
627  template <class VType>
628  static MoveAssignVisitor<VType> MakeMoveAssignVisitor(VType* left,
629  VType* other) {
630  return {left, other};
631  }
632 
633  // The implementation of the assignment operation for a variant.
634  template <class VType>
635  struct CopyAssignVisitor {
636  using DerivedType = typename VType::Variant;
637  template <std::size_t NewIndex>
638  void operator()(SizeT<NewIndex> /*new_i*/) const {
639  using New =
640  typename absl::variant_alternative<NewIndex, DerivedType>::type;
641 
642  if (left->index_ == NewIndex) {
643  Access<NewIndex>(*left) = Access<NewIndex>(*right);
646  Derived(*left).template emplace<NewIndex>(Access<NewIndex>(*right));
647  } else {
648  Derived(*left) = DerivedType(Derived(*right));
649  }
650  }
651 
652  void operator()(SizeT<absl::variant_npos> /*new_i*/) const {
653  Destroy(*left);
654  }
655 
656  VType* left;
657  const VType* right;
658  };
659 
660  template <class VType>
662  const VType& other) {
663  return {left, &other};
664  }
665 
666  // The implementation of conversion-assignment operations for variant.
667  template <class Left, class QualifiedNew>
669  using NewIndex =
671 
673  ) const {
674  Access<NewIndex::value>(*left) = absl::forward<QualifiedNew>(other);
675  }
676 
677  template <std::size_t OldIndex>
679  ) const {
680  using New =
684  left->template emplace<NewIndex::value>(
685  absl::forward<QualifiedNew>(other));
686  } else {
687  // the standard says "equivalent to
688  // operator=(variant(std::forward<T>(t)))", but we use `emplace` here
689  // because the variant's move assignment operator could be deleted.
690  left->template emplace<NewIndex::value>(
691  New(absl::forward<QualifiedNew>(other)));
692  }
693  }
694 
695  Left* left;
696  QualifiedNew&& other;
697  };
698 
699  template <class Left, class QualifiedNew>
701  MakeConversionAssignVisitor(Left* left, QualifiedNew&& qual) {
702  return {left, absl::forward<QualifiedNew>(qual)};
703  }
704 
705  // Backend for operations for `emplace()` which destructs `*self` then
706  // construct a new alternative with `Args...`.
707  template <std::size_t NewIndex, class Self, class... Args>
709  Self* self, Args&&... args) {
710  Destroy(*self);
712  New* const result = ::new (static_cast<void*>(&self->state_))
713  New(absl::forward<Args>(args)...);
714  self->index_ = NewIndex;
715  return *result;
716  }
717 
718  template <class LeftVariant, class QualifiedRightVariant>
720  template <std::size_t NewIndex>
721  void operator()(SizeT<NewIndex> /*new_i*/) const {
722  using Alternative =
724  ::new (static_cast<void*>(&left->state_)) Alternative(
725  Access<NewIndex>(std::forward<QualifiedRightVariant>(right)));
726  }
727 
728  void operator()(SizeT<absl::variant_npos> /*new_i*/) const {
729  // This space intentionally left blank.
730  }
731  LeftVariant* left;
732  QualifiedRightVariant&& right;
733  };
734 };
735 
736 template <class Expected, class... T>
737 struct IndexOfImpl;
738 
739 template <class Expected>
740 struct IndexOfImpl<Expected> {
743  using MultipleMatches = std::false_type;
744 };
745 
746 template <class Expected, class Head, class... Tail>
747 struct IndexOfImpl<Expected, Head, Tail...> : IndexOfImpl<Expected, Tail...> {
748  using IndexFromEnd =
749  SizeT<IndexOfImpl<Expected, Tail...>::IndexFromEnd::value + 1>;
750 };
751 
752 template <class Expected, class... Tail>
753 struct IndexOfImpl<Expected, Expected, Tail...>
754  : IndexOfImpl<Expected, Tail...> {
755  using IndexFromEnd =
756  SizeT<IndexOfImpl<Expected, Tail...>::IndexFromEnd::value + 1>;
757  using MatchedIndexFromEnd = IndexFromEnd;
758  using MultipleMatches = std::integral_constant<
760 };
761 
762 template <class Expected, class... Types>
763 struct IndexOfMeta {
764  using Results = IndexOfImpl<Expected, Types...>;
765  static_assert(!Results::MultipleMatches::value,
766  "Attempted to access a variant by specifying a type that "
767  "matches more than one alternative.");
768  static_assert(Results::MatchedIndexFromEnd::value != 0,
769  "Attempted to access a variant by specifying a type that does "
770  "not match any alternative.");
771  using type = SizeT<sizeof...(Types) - Results::MatchedIndexFromEnd::value>;
772 };
773 
774 template <class Expected, class... Types>
775 using IndexOf = typename IndexOfMeta<Expected, Types...>::type;
776 
777 template <class Variant, class T, std::size_t CurrIndex>
779 
780 // Terminating case encountered once we've checked all of the alternatives
781 template <class T, std::size_t CurrIndex>
782 struct UnambiguousIndexOfImpl<variant<>, T, CurrIndex> : SizeT<CurrIndex> {};
783 
784 // Case where T is not Head
785 template <class Head, class... Tail, class T, std::size_t CurrIndex>
786 struct UnambiguousIndexOfImpl<variant<Head, Tail...>, T, CurrIndex>
787  : UnambiguousIndexOfImpl<variant<Tail...>, T, CurrIndex + 1>::type {};
788 
789 // Case where T is Head
790 template <class Head, class... Tail, std::size_t CurrIndex>
791 struct UnambiguousIndexOfImpl<variant<Head, Tail...>, Head, CurrIndex>
792  : SizeT<UnambiguousIndexOfImpl<variant<Tail...>, Head, 0>::value ==
793  sizeof...(Tail)
794  ? CurrIndex
795  : CurrIndex + sizeof...(Tail) + 1> {};
796 
797 template <class Variant, class T>
799 
800 struct NoMatch {
801  struct type {};
802 };
803 
804 template <class... Alts, class T>
805 struct UnambiguousIndexOf<variant<Alts...>, T>
806  : std::conditional<UnambiguousIndexOfImpl<variant<Alts...>, T, 0>::value !=
807  sizeof...(Alts),
808  UnambiguousIndexOfImpl<variant<Alts...>, T, 0>,
809  NoMatch>::type::type {};
810 
811 template <class T, std::size_t /*Dummy*/>
813 
814 template <class Variant, class T>
815 using UnambiguousTypeOfT =
817 
818 template <class H, class... T>
820 
821 // This is an implementation of the "imaginary function" that is described in
822 // [variant.ctor]
823 // It is used in order to determine which alternative to construct during
824 // initialization from some type T.
825 template <class Variant, std::size_t I = 0>
827 
828 template <std::size_t I>
829 struct ImaginaryFun<variant<>, I> {
830  static void Run() = delete;
831 };
832 
833 template <class H, class... T, std::size_t I>
834 struct ImaginaryFun<variant<H, T...>, I> : ImaginaryFun<variant<T...>, I + 1> {
835  using ImaginaryFun<variant<T...>, I + 1>::Run;
836 
837  // NOTE: const& and && are used instead of by-value due to lack of guaranteed
838  // move elision of C++17. This may have other minor differences, but tests
839  // pass.
840  static SizeT<I> Run(const H&);
841  static SizeT<I> Run(H&&);
842 };
843 
844 // The following metafunctions are used in constructor and assignment
845 // constraints.
846 template <class Self, class T>
847 struct IsNeitherSelfNorInPlace : std::true_type {};
848 
849 template <class Self>
850 struct IsNeitherSelfNorInPlace<Self, Self> : std::false_type {};
851 
852 template <class Self, class T>
853 struct IsNeitherSelfNorInPlace<Self, in_place_type_t<T>> : std::false_type {};
854 
855 template <class Self, std::size_t I>
856 struct IsNeitherSelfNorInPlace<Self, in_place_index_t<I>> : std::false_type {};
857 
858 template <class Variant, class T, class = void>
859 struct ConversionIsPossibleImpl : std::false_type {};
860 
861 template <class Variant, class T>
863  Variant, T, void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>()))>>
864  : std::true_type {};
865 
866 template <class Variant, class T>
867 struct ConversionIsPossible : ConversionIsPossibleImpl<Variant, T>::type {};
868 
869 template <class Variant, class T>
871  Variant, T, void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>()))>>
872  : decltype(ImaginaryFun<Variant>::Run(std::declval<T>())) {};
873 
874 template <std::size_t... Is>
875 struct ContainsVariantNPos
876  : absl::negation<std::is_same< // NOLINT
877  absl::integer_sequence<bool, 0 <= Is...>,
878  absl::integer_sequence<bool, Is != absl::variant_npos...>>> {};
879 
880 template <class Op, class... QualifiedVariants>
881 using RawVisitResult =
882  absl::result_of_t<Op(VariantAccessResult<0, QualifiedVariants>...)>;
883 
884 // NOTE: The spec requires that all return-paths yield the same type and is not
885 // SFINAE-friendly, so we can deduce the return type by examining the first
886 // result. If it's not callable, then we get an error, but are compliant and
887 // fast to compile.
888 // TODO(calabrese) Possibly rewrite in a way that yields better compile errors
889 // at the cost of longer compile-times.
890 template <class Op, class... QualifiedVariants>
891 struct VisitResultImpl {
892  using type =
893  absl::result_of_t<Op(VariantAccessResult<0, QualifiedVariants>...)>;
894 };
895 
896 // Done in two steps intentionally so that we don't cause substitution to fail.
897 template <class Op, class... QualifiedVariants>
898 using VisitResult = typename VisitResultImpl<Op, QualifiedVariants...>::type;
899 
900 template <class Op, class... QualifiedVariants>
901 struct PerformVisitation {
902  using ReturnType = VisitResult<Op, QualifiedVariants...>;
903 
904  template <std::size_t... Is>
905  constexpr ReturnType operator()(SizeT<Is>... indices) const {
906  return Run(typename ContainsVariantNPos<Is...>::type{},
907  absl::index_sequence_for<QualifiedVariants...>(), indices...);
908  }
909 
910  template <std::size_t... TupIs, std::size_t... Is>
911  constexpr ReturnType Run(std::false_type /*has_valueless*/,
912  index_sequence<TupIs...>, SizeT<Is>...) const {
913  static_assert(
914  std::is_same<ReturnType,
915  absl::result_of_t<Op(VariantAccessResult<
916  Is, QualifiedVariants>...)>>::value,
917  "All visitation overloads must have the same return type.");
918  return absl::base_internal::Invoke(
919  absl::forward<Op>(op),
920  VariantCoreAccess::Access<Is>(
921  absl::forward<QualifiedVariants>(std::get<TupIs>(variant_tup)))...);
922  }
923 
924  template <std::size_t... TupIs, std::size_t... Is>
925  [[noreturn]] ReturnType Run(std::true_type /*has_valueless*/,
926  index_sequence<TupIs...>, SizeT<Is>...) const {
927  absl::variant_internal::ThrowBadVariantAccess();
928  }
929 
930  // TODO(calabrese) Avoid using a tuple, which causes lots of instantiations
931  // Attempts using lambda variadic captures fail on current GCC.
932  std::tuple<QualifiedVariants&&...> variant_tup;
933  Op&& op;
934 };
935 
936 template <class... T>
937 union Union;
938 
939 // We want to allow for variant<> to be trivial. For that, we need the default
940 // constructor to be trivial, which means we can't define it ourselves.
941 // Instead, we use a non-default constructor that takes NoopConstructorTag
942 // that doesn't affect the triviality of the types.
943 struct NoopConstructorTag {};
944 
945 template <std::size_t I>
946 struct EmplaceTag {};
947 
948 template <>
949 union Union<> {
950  constexpr explicit Union(NoopConstructorTag) noexcept {}
951 };
952 
953 // Suppress bogus warning on MSVC: MSVC complains that Union<T...> has a defined
954 // deleted destructor from the `std::is_destructible` check below.
955 #ifdef _MSC_VER
956 #pragma warning(push)
957 #pragma warning(disable : 4624)
958 #endif // _MSC_VER
959 
960 template <class Head, class... Tail>
961 union Union<Head, Tail...> {
962  using TailUnion = Union<Tail...>;
963 
964  explicit constexpr Union(NoopConstructorTag /*tag*/) noexcept
965  : tail(NoopConstructorTag()) {}
966 
967  template <class... P>
968  explicit constexpr Union(EmplaceTag<0>, P&&... args)
969  : head(absl::forward<P>(args)...) {}
970 
971  template <std::size_t I, class... P>
972  explicit constexpr Union(EmplaceTag<I>, P&&... args)
973  : tail(EmplaceTag<I - 1>{}, absl::forward<P>(args)...) {}
974 
975  Head head;
976  TailUnion tail;
977 };
978 
979 #ifdef _MSC_VER
980 #pragma warning(pop)
981 #endif // _MSC_VER
982 
983 // TODO(calabrese) Just contain a Union in this union (certain configs fail).
984 template <class... T>
985 union DestructibleUnionImpl;
986 
987 template <>
988 union DestructibleUnionImpl<> {
989  constexpr explicit DestructibleUnionImpl(NoopConstructorTag) noexcept {}
990 };
991 
992 template <class Head, class... Tail>
993 union DestructibleUnionImpl<Head, Tail...> {
994  using TailUnion = DestructibleUnionImpl<Tail...>;
995 
996  explicit constexpr DestructibleUnionImpl(NoopConstructorTag /*tag*/) noexcept
997  : tail(NoopConstructorTag()) {}
998 
999  template <class... P>
1000  explicit constexpr DestructibleUnionImpl(EmplaceTag<0>, P&&... args)
1001  : head(absl::forward<P>(args)...) {}
1002 
1003  template <std::size_t I, class... P>
1004  explicit constexpr DestructibleUnionImpl(EmplaceTag<I>, P&&... args)
1005  : tail(EmplaceTag<I - 1>{}, absl::forward<P>(args)...) {}
1006 
1007  ~DestructibleUnionImpl() {}
1008 
1009  Head head;
1010  TailUnion tail;
1011 };
1012 
1013 // This union type is destructible even if one or more T are not trivially
1014 // destructible. In the case that all T are trivially destructible, then so is
1015 // this resultant type.
1016 template <class... T>
1017 using DestructibleUnion =
1018  absl::conditional_t<std::is_destructible<Union<T...>>::value, Union<T...>,
1019  DestructibleUnionImpl<T...>>;
1020 
1021 // Deepest base, containing the actual union and the discriminator
1022 template <class H, class... T>
1023 class VariantStateBase {
1024  protected:
1025  using Variant = variant<H, T...>;
1026 
1027  template <class LazyH = H,
1028  class ConstructibleH = absl::enable_if_t<
1029  std::is_default_constructible<LazyH>::value, LazyH>>
1030  constexpr VariantStateBase() noexcept(
1031  std::is_nothrow_default_constructible<ConstructibleH>::value)
1032  : state_(EmplaceTag<0>()), index_(0) {}
1033 
1034  template <std::size_t I, class... P>
1035  explicit constexpr VariantStateBase(EmplaceTag<I> tag, P&&... args)
1036  : state_(tag, absl::forward<P>(args)...), index_(I) {}
1037 
1038  explicit constexpr VariantStateBase(NoopConstructorTag)
1039  : state_(NoopConstructorTag()), index_(variant_npos) {}
1040 
1041  void destroy() {} // Does nothing (shadowed in child if non-trivial)
1042 
1043  DestructibleUnion<H, T...> state_;
1044  std::size_t index_;
1045 };
1046 
1047 using absl::internal::identity;
1048 
1049 // OverloadSet::Overload() is a unary function which is overloaded to
1050 // take any of the element types of the variant, by reference-to-const.
1051 // The return type of the overload on T is identity<T>, so that you
1052 // can statically determine which overload was called.
1053 //
1054 // Overload() is not defined, so it can only be called in unevaluated
1055 // contexts.
1056 template <typename... Ts>
1057 struct OverloadSet;
1058 
1059 template <typename T, typename... Ts>
1060 struct OverloadSet<T, Ts...> : OverloadSet<Ts...> {
1061  using Base = OverloadSet<Ts...>;
1062  static identity<T> Overload(const T&);
1063  using Base::Overload;
1064 };
1065 
1066 template <>
1067 struct OverloadSet<> {
1068  // For any case not handled above.
1069  static void Overload(...);
1070 };
1071 
1072 template <class T>
1073 using LessThanResult = decltype(std::declval<T>() < std::declval<T>());
1074 
1075 template <class T>
1076 using GreaterThanResult = decltype(std::declval<T>() > std::declval<T>());
1077 
1078 template <class T>
1079 using LessThanOrEqualResult = decltype(std::declval<T>() <= std::declval<T>());
1080 
1081 template <class T>
1082 using GreaterThanOrEqualResult =
1083  decltype(std::declval<T>() >= std::declval<T>());
1084 
1085 template <class T>
1086 using EqualResult = decltype(std::declval<T>() == std::declval<T>());
1087 
1088 template <class T>
1089 using NotEqualResult = decltype(std::declval<T>() != std::declval<T>());
1090 
1091 using type_traits_internal::is_detected_convertible;
1092 
1093 template <class... T>
1094 using RequireAllHaveEqualT = absl::enable_if_t<
1095  absl::conjunction<is_detected_convertible<bool, EqualResult, T>...>::value,
1096  bool>;
1097 
1098 template <class... T>
1099 using RequireAllHaveNotEqualT =
1100  absl::enable_if_t<absl::conjunction<is_detected_convertible<
1101  bool, NotEqualResult, T>...>::value,
1102  bool>;
1103 
1104 template <class... T>
1105 using RequireAllHaveLessThanT =
1106  absl::enable_if_t<absl::conjunction<is_detected_convertible<
1107  bool, LessThanResult, T>...>::value,
1108  bool>;
1109 
1110 template <class... T>
1111 using RequireAllHaveLessThanOrEqualT =
1112  absl::enable_if_t<absl::conjunction<is_detected_convertible<
1113  bool, LessThanOrEqualResult, T>...>::value,
1114  bool>;
1115 
1116 template <class... T>
1117 using RequireAllHaveGreaterThanOrEqualT =
1118  absl::enable_if_t<absl::conjunction<is_detected_convertible<
1119  bool, GreaterThanOrEqualResult, T>...>::value,
1120  bool>;
1121 
1122 template <class... T>
1123 using RequireAllHaveGreaterThanT =
1124  absl::enable_if_t<absl::conjunction<is_detected_convertible<
1125  bool, GreaterThanResult, T>...>::value,
1126  bool>;
1127 
1128 // Helper template containing implementations details of variant that can't go
1129 // in the private section. For convenience, this takes the variant type as a
1130 // single template parameter.
1131 template <typename T>
1132 struct VariantHelper;
1133 
1134 template <typename... Ts>
1135 struct VariantHelper<variant<Ts...>> {
1136  // Type metafunction which returns the element type selected if
1137  // OverloadSet::Overload() is well-formed when called with argument type U.
1138  template <typename U>
1139  using BestMatch = decltype(
1140  variant_internal::OverloadSet<Ts...>::Overload(std::declval<U>()));
1141 
1142  // Type metafunction which returns true if OverloadSet::Overload() is
1143  // well-formed when called with argument type U.
1144  // CanAccept can't be just an alias because there is a MSVC bug on parameter
1145  // pack expansion involving decltype.
1146  template <typename U>
1147  struct CanAccept :
1148  std::integral_constant<bool, !std::is_void<BestMatch<U>>::value> {};
1149 
1150  // Type metafunction which returns true if Other is an instantiation of
1151  // variant, and variants's converting constructor from Other will be
1152  // well-formed. We will use this to remove constructors that would be
1153  // ill-formed from the overload set.
1154  template <typename Other>
1155  struct CanConvertFrom;
1156 
1157  template <typename... Us>
1158  struct CanConvertFrom<variant<Us...>>
1159  : public absl::conjunction<CanAccept<Us>...> {};
1160 };
1161 
1162 // A type with nontrivial copy ctor and trivial move ctor.
1163 struct TrivialMoveOnly {
1164  TrivialMoveOnly(TrivialMoveOnly&&) = default;
1165 };
1166 
1167 // Trait class to detect whether a type is trivially move constructible.
1168 // A union's defaulted copy/move constructor is deleted if any variant member's
1169 // copy/move constructor is nontrivial.
1170 template <typename T>
1171 struct IsTriviallyMoveConstructible:
1172  std::is_move_constructible<Union<T, TrivialMoveOnly>> {};
1173 
1174 // To guarantee triviality of all special-member functions that can be trivial,
1175 // we use a chain of conditional bases for each one.
1176 // The order of inheritance of bases from child to base are logically:
1177 //
1178 // variant
1179 // VariantCopyAssignBase
1180 // VariantMoveAssignBase
1181 // VariantCopyBase
1182 // VariantMoveBase
1183 // VariantStateBaseDestructor
1184 // VariantStateBase
1185 //
1186 // Note that there is a separate branch at each base that is dependent on
1187 // whether or not that corresponding special-member-function can be trivial in
1188 // the resultant variant type.
1189 
1190 template <class... T>
1191 class VariantStateBaseDestructorNontrivial;
1192 
1193 template <class... T>
1194 class VariantMoveBaseNontrivial;
1195 
1196 template <class... T>
1197 class VariantCopyBaseNontrivial;
1198 
1199 template <class... T>
1200 class VariantMoveAssignBaseNontrivial;
1201 
1202 template <class... T>
1203 class VariantCopyAssignBaseNontrivial;
1204 
1205 // Base that is dependent on whether or not the destructor can be trivial.
1206 template <class... T>
1207 using VariantStateBaseDestructor =
1208  absl::conditional_t<std::is_destructible<Union<T...>>::value,
1209  VariantStateBase<T...>,
1210  VariantStateBaseDestructorNontrivial<T...>>;
1211 
1212 // Base that is dependent on whether or not the move-constructor can be
1213 // implicitly generated by the compiler (trivial or deleted).
1214 // Previously we were using `std::is_move_constructible<Union<T...>>` to check
1215 // whether all Ts have trivial move constructor, but it ran into a GCC bug:
1216 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84866
1217 // So we have to use a different approach (i.e. `HasTrivialMoveConstructor`) to
1218 // work around the bug.
1219 template <class... T>
1220 using VariantMoveBase = absl::conditional_t<
1221  absl::disjunction<
1222  absl::negation<absl::conjunction<std::is_move_constructible<T>...>>,
1223  absl::conjunction<IsTriviallyMoveConstructible<T>...>>::value,
1224  VariantStateBaseDestructor<T...>, VariantMoveBaseNontrivial<T...>>;
1225 
1226 // Base that is dependent on whether or not the copy-constructor can be trivial.
1227 template <class... T>
1228 using VariantCopyBase = absl::conditional_t<
1229  absl::disjunction<
1230  absl::negation<absl::conjunction<std::is_copy_constructible<T>...>>,
1231  std::is_copy_constructible<Union<T...>>>::value,
1232  VariantMoveBase<T...>, VariantCopyBaseNontrivial<T...>>;
1233 
1234 // Base that is dependent on whether or not the move-assign can be trivial.
1235 template <class... T>
1236 using VariantMoveAssignBase = absl::conditional_t<
1237  absl::disjunction<
1238  absl::conjunction<absl::is_move_assignable<Union<T...>>,
1239  std::is_move_constructible<Union<T...>>,
1240  std::is_destructible<Union<T...>>>,
1241  absl::negation<absl::conjunction<std::is_move_constructible<T>...,
1242  // Note: We're not qualifying this with
1243  // absl:: because it doesn't compile
1244  // under MSVC.
1245  is_move_assignable<T>...>>>::value,
1246  VariantCopyBase<T...>, VariantMoveAssignBaseNontrivial<T...>>;
1247 
1248 // Base that is dependent on whether or not the copy-assign can be trivial.
1249 template <class... T>
1250 using VariantCopyAssignBase = absl::conditional_t<
1251  absl::disjunction<
1252  absl::conjunction<absl::is_copy_assignable<Union<T...>>,
1253  std::is_copy_constructible<Union<T...>>,
1254  std::is_destructible<Union<T...>>>,
1255  absl::negation<absl::conjunction<std::is_copy_constructible<T>...,
1256  // Note: We're not qualifying this with
1257  // absl:: because it doesn't compile
1258  // under MSVC.
1259  is_copy_assignable<T>...>>>::value,
1260  VariantMoveAssignBase<T...>, VariantCopyAssignBaseNontrivial<T...>>;
1261 
1262 template <class... T>
1263 using VariantBase = VariantCopyAssignBase<T...>;
1264 
1265 template <class... T>
1266 class VariantStateBaseDestructorNontrivial : protected VariantStateBase<T...> {
1267  private:
1268  using Base = VariantStateBase<T...>;
1269 
1270  protected:
1271  using Base::Base;
1272 
1273  VariantStateBaseDestructorNontrivial() = default;
1274  VariantStateBaseDestructorNontrivial(VariantStateBaseDestructorNontrivial&&) =
1275  default;
1276  VariantStateBaseDestructorNontrivial(
1277  const VariantStateBaseDestructorNontrivial&) = default;
1278  VariantStateBaseDestructorNontrivial& operator=(
1279  VariantStateBaseDestructorNontrivial&&) = default;
1280  VariantStateBaseDestructorNontrivial& operator=(
1281  const VariantStateBaseDestructorNontrivial&) = default;
1282 
1283  struct Destroyer {
1284  template <std::size_t I>
1285  void operator()(SizeT<I> i) const {
1286  using Alternative =
1287  typename absl::variant_alternative<I, variant<T...>>::type;
1288  variant_internal::AccessUnion(self->state_, i).~Alternative();
1289  }
1290 
1291  void operator()(SizeT<absl::variant_npos> /*i*/) const {
1292  // This space intentionally left blank
1293  }
1294 
1295  VariantStateBaseDestructorNontrivial* self;
1296  };
1297 
1298  void destroy() { VisitIndices<sizeof...(T)>::Run(Destroyer{this}, index_); }
1299 
1300  ~VariantStateBaseDestructorNontrivial() { destroy(); }
1301 
1302  protected:
1303  using Base::index_;
1304  using Base::state_;
1305 };
1306 
1307 template <class... T>
1308 class VariantMoveBaseNontrivial : protected VariantStateBaseDestructor<T...> {
1309  private:
1310  using Base = VariantStateBaseDestructor<T...>;
1311 
1312  protected:
1313  using Base::Base;
1314 
1315  struct Construct {
1316  template <std::size_t I>
1317  void operator()(SizeT<I> i) const {
1318  using Alternative =
1319  typename absl::variant_alternative<I, variant<T...>>::type;
1320  ::new (static_cast<void*>(&self->state_)) Alternative(
1321  variant_internal::AccessUnion(absl::move(other->state_), i));
1322  }
1323 
1324  void operator()(SizeT<absl::variant_npos> /*i*/) const {}
1325 
1326  VariantMoveBaseNontrivial* self;
1327  VariantMoveBaseNontrivial* other;
1328  };
1329 
1330  VariantMoveBaseNontrivial() = default;
1331  VariantMoveBaseNontrivial(VariantMoveBaseNontrivial&& other) noexcept(
1332  absl::conjunction<std::is_nothrow_move_constructible<T>...>::value)
1333  : Base(NoopConstructorTag()) {
1334  VisitIndices<sizeof...(T)>::Run(Construct{this, &other}, other.index_);
1335  index_ = other.index_;
1336  }
1337 
1338  VariantMoveBaseNontrivial(VariantMoveBaseNontrivial const&) = default;
1339 
1340  VariantMoveBaseNontrivial& operator=(VariantMoveBaseNontrivial&&) = default;
1341  VariantMoveBaseNontrivial& operator=(VariantMoveBaseNontrivial const&) =
1342  default;
1343 
1344  protected:
1345  using Base::index_;
1346  using Base::state_;
1347 };
1348 
1349 template <class... T>
1350 class VariantCopyBaseNontrivial : protected VariantMoveBase<T...> {
1351  private:
1352  using Base = VariantMoveBase<T...>;
1353 
1354  protected:
1355  using Base::Base;
1356 
1357  VariantCopyBaseNontrivial() = default;
1358  VariantCopyBaseNontrivial(VariantCopyBaseNontrivial&&) = default;
1359 
1360  struct Construct {
1361  template <std::size_t I>
1362  void operator()(SizeT<I> i) const {
1363  using Alternative =
1364  typename absl::variant_alternative<I, variant<T...>>::type;
1365  ::new (static_cast<void*>(&self->state_))
1366  Alternative(variant_internal::AccessUnion(other->state_, i));
1367  }
1368 
1369  void operator()(SizeT<absl::variant_npos> /*i*/) const {}
1370 
1371  VariantCopyBaseNontrivial* self;
1372  const VariantCopyBaseNontrivial* other;
1373  };
1374 
1375  VariantCopyBaseNontrivial(VariantCopyBaseNontrivial const& other)
1376  : Base(NoopConstructorTag()) {
1377  VisitIndices<sizeof...(T)>::Run(Construct{this, &other}, other.index_);
1378  index_ = other.index_;
1379  }
1380 
1381  VariantCopyBaseNontrivial& operator=(VariantCopyBaseNontrivial&&) = default;
1382  VariantCopyBaseNontrivial& operator=(VariantCopyBaseNontrivial const&) =
1383  default;
1384 
1385  protected:
1386  using Base::index_;
1387  using Base::state_;
1388 };
1389 
1390 template <class... T>
1391 class VariantMoveAssignBaseNontrivial : protected VariantCopyBase<T...> {
1392  friend struct VariantCoreAccess;
1393 
1394  private:
1395  using Base = VariantCopyBase<T...>;
1396 
1397  protected:
1398  using Base::Base;
1399 
1400  VariantMoveAssignBaseNontrivial() = default;
1401  VariantMoveAssignBaseNontrivial(VariantMoveAssignBaseNontrivial&&) = default;
1402  VariantMoveAssignBaseNontrivial(const VariantMoveAssignBaseNontrivial&) =
1403  default;
1404  VariantMoveAssignBaseNontrivial& operator=(
1405  VariantMoveAssignBaseNontrivial const&) = default;
1406 
1407  VariantMoveAssignBaseNontrivial&
1408  operator=(VariantMoveAssignBaseNontrivial&& other) noexcept(
1409  absl::conjunction<std::is_nothrow_move_constructible<T>...,
1410  std::is_nothrow_move_assignable<T>...>::value) {
1411  VisitIndices<sizeof...(T)>::Run(
1412  VariantCoreAccess::MakeMoveAssignVisitor(this, &other), other.index_);
1413  return *this;
1414  }
1415 
1416  protected:
1417  using Base::index_;
1418  using Base::state_;
1419 };
1420 
1421 template <class... T>
1422 class VariantCopyAssignBaseNontrivial : protected VariantMoveAssignBase<T...> {
1423  friend struct VariantCoreAccess;
1424 
1425  private:
1426  using Base = VariantMoveAssignBase<T...>;
1427 
1428  protected:
1429  using Base::Base;
1430 
1431  VariantCopyAssignBaseNontrivial() = default;
1432  VariantCopyAssignBaseNontrivial(VariantCopyAssignBaseNontrivial&&) = default;
1433  VariantCopyAssignBaseNontrivial(const VariantCopyAssignBaseNontrivial&) =
1434  default;
1435  VariantCopyAssignBaseNontrivial& operator=(
1436  VariantCopyAssignBaseNontrivial&&) = default;
1437 
1438  VariantCopyAssignBaseNontrivial& operator=(
1439  const VariantCopyAssignBaseNontrivial& other) {
1440  VisitIndices<sizeof...(T)>::Run(
1441  VariantCoreAccess::MakeCopyAssignVisitor(this, other), other.index_);
1442  return *this;
1443  }
1444 
1445  protected:
1446  using Base::index_;
1447  using Base::state_;
1448 };
1449 
1451 // Visitors for Comparison Operations //
1453 
1454 template <class... Types>
1455 struct EqualsOp {
1456  const variant<Types...>* v;
1457  const variant<Types...>* w;
1458 
1459  constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
1460  return true;
1461  }
1462 
1463  template <std::size_t I>
1464  constexpr bool operator()(SizeT<I> /*v_i*/) const {
1465  return VariantCoreAccess::Access<I>(*v) == VariantCoreAccess::Access<I>(*w);
1466  }
1467 };
1468 
1469 template <class... Types>
1470 struct NotEqualsOp {
1471  const variant<Types...>* v;
1472  const variant<Types...>* w;
1473 
1474  constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
1475  return false;
1476  }
1477 
1478  template <std::size_t I>
1479  constexpr bool operator()(SizeT<I> /*v_i*/) const {
1480  return VariantCoreAccess::Access<I>(*v) != VariantCoreAccess::Access<I>(*w);
1481  }
1482 };
1483 
1484 template <class... Types>
1485 struct LessThanOp {
1486  const variant<Types...>* v;
1487  const variant<Types...>* w;
1488 
1489  constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
1490  return false;
1491  }
1492 
1493  template <std::size_t I>
1494  constexpr bool operator()(SizeT<I> /*v_i*/) const {
1495  return VariantCoreAccess::Access<I>(*v) < VariantCoreAccess::Access<I>(*w);
1496  }
1497 };
1498 
1499 template <class... Types>
1500 struct GreaterThanOp {
1501  const variant<Types...>* v;
1502  const variant<Types...>* w;
1503 
1504  constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
1505  return false;
1506  }
1507 
1508  template <std::size_t I>
1509  constexpr bool operator()(SizeT<I> /*v_i*/) const {
1510  return VariantCoreAccess::Access<I>(*v) > VariantCoreAccess::Access<I>(*w);
1511  }
1512 };
1513 
1514 template <class... Types>
1515 struct LessThanOrEqualsOp {
1516  const variant<Types...>* v;
1517  const variant<Types...>* w;
1518 
1519  constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
1520  return true;
1521  }
1522 
1523  template <std::size_t I>
1524  constexpr bool operator()(SizeT<I> /*v_i*/) const {
1525  return VariantCoreAccess::Access<I>(*v) <= VariantCoreAccess::Access<I>(*w);
1526  }
1527 };
1528 
1529 template <class... Types>
1530 struct GreaterThanOrEqualsOp {
1531  const variant<Types...>* v;
1532  const variant<Types...>* w;
1533 
1534  constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
1535  return true;
1536  }
1537 
1538  template <std::size_t I>
1539  constexpr bool operator()(SizeT<I> /*v_i*/) const {
1540  return VariantCoreAccess::Access<I>(*v) >= VariantCoreAccess::Access<I>(*w);
1541  }
1542 };
1543 
1544 // Precondition: v.index() == w.index();
1545 template <class... Types>
1546 struct SwapSameIndex {
1547  variant<Types...>* v;
1548  variant<Types...>* w;
1549  template <std::size_t I>
1550  void operator()(SizeT<I>) const {
1551  type_traits_internal::Swap(VariantCoreAccess::Access<I>(*v),
1552  VariantCoreAccess::Access<I>(*w));
1553  }
1554 
1555  void operator()(SizeT<variant_npos>) const {}
1556 };
1557 
1558 // TODO(calabrese) do this from a different namespace for proper adl usage
1559 template <class... Types>
1560 struct Swap {
1561  variant<Types...>* v;
1562  variant<Types...>* w;
1563 
1564  void generic_swap() const {
1565  variant<Types...> tmp(std::move(*w));
1570  }
1571 
1572  void operator()(SizeT<absl::variant_npos> /*w_i*/) const {
1573  if (!v->valueless_by_exception()) {
1574  generic_swap();
1575  }
1576  }
1577 
1578  template <std::size_t Wi>
1579  void operator()(SizeT<Wi> /*w_i*/) {
1580  if (v->index() == Wi) {
1581  VisitIndices<sizeof...(Types)>::Run(SwapSameIndex<Types...>{v, w}, Wi);
1582  } else {
1583  generic_swap();
1584  }
1585  }
1586 };
1587 
1588 template <typename Variant, typename = void, typename... Ts>
1589 struct VariantHashBase {
1590  VariantHashBase() = delete;
1591  VariantHashBase(const VariantHashBase&) = delete;
1592  VariantHashBase(VariantHashBase&&) = delete;
1593  VariantHashBase& operator=(const VariantHashBase&) = delete;
1594  VariantHashBase& operator=(VariantHashBase&&) = delete;
1595 };
1596 
1597 struct VariantHashVisitor {
1598  template <typename T>
1599  size_t operator()(const T& t) {
1600  return std::hash<T>{}(t);
1601  }
1602 };
1603 
1604 template <typename Variant, typename... Ts>
1605 struct VariantHashBase<Variant,
1606  absl::enable_if_t<absl::conjunction<
1607  type_traits_internal::IsHashable<Ts>...>::value>,
1608  Ts...> {
1609  using argument_type = Variant;
1610  using result_type = size_t;
1611  size_t operator()(const Variant& var) const {
1613  if (var.valueless_by_exception()) {
1614  return 239799884;
1615  }
1616  size_t result = VisitIndices<variant_size<Variant>::value>::Run(
1617  PerformVisitation<VariantHashVisitor, const Variant&>{
1618  std::forward_as_tuple(var), VariantHashVisitor{}},
1619  var.index());
1620  // Combine the index and the hash result in order to distinguish
1621  // std::variant<int, int> holding the same value as different alternative.
1622  return result ^ var.index();
1623  }
1624 };
1625 
1626 } // namespace variant_internal
1627 } // namespace absl
1628 
1629 #endif // !defined(ABSL_HAVE_STD_VARIANT)
1630 #endif // ABSL_TYPES_variant_internal_H_
int v
Definition: variant_test.cc:81
static constexpr std::size_t Run()
typename absl::variant_alternative< I, variant< T... > >::type & type
const typename absl::variant_alternative< I, variant< T... > >::type && type
typename std::result_of< T >::type result_of_t
Definition: type_traits.h:559
void operator()(SizeT< absl::variant_npos >) const
constexpr T AccessSimpleArray(const T &value)
VariantAccessResult< I, Self > AccessUnion(Self &&self, SizeT< I >)
static VisitIndicesResultT< Op, std::size_t > Run(Op &&op)
UnambiguousTypeOfImpl< T, UnambiguousIndexOf< Variant, T >::value > UnambiguousTypeOfT
static ConversionAssignVisitor< Left, QualifiedNew > MakeConversionAssignVisitor(Left *left, QualifiedNew &&qual)
#define ABSL_ASSERT(expr)
Definition: macros.h:198
static void Destroy(VariantType &self)
typename GiveQualsTo< T, U >::type GiveQualsToT
SizeT< IndexOfImpl< Expected, Tail... >::IndexFromEnd::value+1 > IndexFromEnd
static VisitIndicesResultT< Op, std::size_t > Run(Op &&)
typename VariantAccessResultImpl< I, Variant && >::type VariantAccessResult
ReturnType TypedThrowBadVariantAccess()
static void InitFrom(Variant &self, Variant &&other)
typename AccessedType< T >::type AccessedTypeT
constexpr ReturnType call_with_indices(FunctionObject &&function)
typename VariantAlternativeSfinae< I, T >::type VariantAlternativeSfinaeT
void(*)(utility_internal::InPlaceTypeTag< T >) in_place_type_t
Definition: utility.h:189
Definition: algorithm.h:29
SizeT< sizeof...(Types) - Results::MatchedIndexFromEnd::value > type
typename std::conditional< B, T, F >::type conditional_t
Definition: type_traits.h:550
static VisitIndicesResultT< Op, std::size_t > Run(Op &&op, std::size_t i)
typename std::enable_if< B, T >::type enable_if_t
Definition: type_traits.h:547
static CopyAssignVisitor< VType > MakeCopyAssignVisitor(VType *left, const VType &other)
static absl::variant_alternative< NewIndex, Self >::type & Replace(Self *self, Args &&... args)
static std::function< void(void *, Slot *)> destroy
SizeT< variant_npos > NPos
void Swap(T &lhs, T &rhs) noexcept(IsNothrowSwappable< T >::value)
Definition: type_traits.h:673
std::integral_constant< std::size_t, I > SizeT
typename VisitIndicesResultImpl< Op, Vs... >::type VisitIndicesResultT
size_t value
SizeT< IndexOfImpl< Expected, Tail... >::IndexFromEnd::value+1 > IndexFromEnd
const typename absl::variant_alternative< I, variant< T... > >::type & type
typename type_traits_internal::VoidTImpl< Ts... >::type void_t
Definition: type_traits.h:171
static constexpr std::size_t Run(std::size_t head, SizeType... tail)
typename absl::variant_alternative< I, variant< T... > >::type && type
void(*)(utility_internal::InPlaceIndexTag< I >) in_place_index_t
Definition: utility.h:206
InvokeT< F, Args... > Invoke(F &&f, Args &&... args)
Definition: invoke.h:181
ABSL_INTERNAL_INLINE_CONSTEXPR(std::size_t, MaxUnrolledVisitCases, 33)
std::integral_constant< bool, IndexOfImpl< Expected, Tail... >::MatchedIndexFromEnd::value !=0 > MultipleMatches
std::shared_ptr< AllocState > state_
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: utility.h:219
ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, -1)
typename IndexOfMeta< Expected, Types... >::type IndexOf
static VisitIndicesResultT< Op, decltype(EndIndices)... > Run(Op &&op, SizeType... i)
static MoveAssignVisitor< VType > MakeMoveAssignVisitor(VType *left, VType *other)
typename PickCaseImpl<(I< EndIndex)>::template Apply< Op, I > PickCase
absl::result_of_t< Op(AlwaysZero< Vs >...)> type
static VisitIndicesResultT< Op, SizeT... > Run(Op &&op, SizeT... indices)


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