Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:41:08

0001 // Copyright 2018 The Abseil Authors.
0002 //
0003 // Licensed under the Apache License, Version 2.0 (the "License");
0004 // you may not use this file except in compliance with the License.
0005 // You may obtain a copy of the License at
0006 //
0007 //      https://www.apache.org/licenses/LICENSE-2.0
0008 //
0009 // Unless required by applicable law or agreed to in writing, software
0010 // distributed under the License is distributed on an "AS IS" BASIS,
0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012 // See the License for the specific language governing permissions and
0013 // limitations under the License.
0014 //
0015 // Implementation details of absl/types/variant.h, pulled into a
0016 // separate file to avoid cluttering the top of the API header with
0017 // implementation details.
0018 
0019 #ifndef ABSL_TYPES_INTERNAL_VARIANT_H_
0020 #define ABSL_TYPES_INTERNAL_VARIANT_H_
0021 
0022 #include <cassert>
0023 #include <cstddef>
0024 #include <cstdlib>
0025 #include <memory>
0026 #include <stdexcept>
0027 #include <tuple>
0028 #include <type_traits>
0029 #include <utility>
0030 
0031 #include "absl/base/config.h"
0032 #include "absl/base/internal/identity.h"
0033 #include "absl/base/internal/inline_variable.h"
0034 #include "absl/base/internal/invoke.h"
0035 #include "absl/base/macros.h"
0036 #include "absl/base/optimization.h"
0037 #include "absl/meta/type_traits.h"
0038 #include "absl/types/bad_variant_access.h"
0039 #include "absl/utility/utility.h"
0040 
0041 #if !defined(ABSL_USES_STD_VARIANT)
0042 
0043 namespace absl {
0044 ABSL_NAMESPACE_BEGIN
0045 
0046 template <class... Types>
0047 class variant;
0048 
0049 ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, static_cast<size_t>(-1));
0050 
0051 template <class T>
0052 struct variant_size;
0053 
0054 template <std::size_t I, class T>
0055 struct variant_alternative;
0056 
0057 namespace variant_internal {
0058 
0059 // NOTE: See specializations below for details.
0060 template <std::size_t I, class T>
0061 struct VariantAlternativeSfinae {};
0062 
0063 // Requires: I < variant_size_v<T>.
0064 //
0065 // Value: The Ith type of Types...
0066 template <std::size_t I, class T0, class... Tn>
0067 struct VariantAlternativeSfinae<I, variant<T0, Tn...>>
0068     : VariantAlternativeSfinae<I - 1, variant<Tn...>> {};
0069 
0070 // Value: T0
0071 template <class T0, class... Ts>
0072 struct VariantAlternativeSfinae<0, variant<T0, Ts...>> {
0073   using type = T0;
0074 };
0075 
0076 template <std::size_t I, class T>
0077 using VariantAlternativeSfinaeT = typename VariantAlternativeSfinae<I, T>::type;
0078 
0079 // NOTE: Requires T to be a reference type.
0080 template <class T, class U>
0081 struct GiveQualsTo;
0082 
0083 template <class T, class U>
0084 struct GiveQualsTo<T&, U> {
0085   using type = U&;
0086 };
0087 
0088 template <class T, class U>
0089 struct GiveQualsTo<T&&, U> {
0090   using type = U&&;
0091 };
0092 
0093 template <class T, class U>
0094 struct GiveQualsTo<const T&, U> {
0095   using type = const U&;
0096 };
0097 
0098 template <class T, class U>
0099 struct GiveQualsTo<const T&&, U> {
0100   using type = const U&&;
0101 };
0102 
0103 template <class T, class U>
0104 struct GiveQualsTo<volatile T&, U> {
0105   using type = volatile U&;
0106 };
0107 
0108 template <class T, class U>
0109 struct GiveQualsTo<volatile T&&, U> {
0110   using type = volatile U&&;
0111 };
0112 
0113 template <class T, class U>
0114 struct GiveQualsTo<volatile const T&, U> {
0115   using type = volatile const U&;
0116 };
0117 
0118 template <class T, class U>
0119 struct GiveQualsTo<volatile const T&&, U> {
0120   using type = volatile const U&&;
0121 };
0122 
0123 template <class T, class U>
0124 using GiveQualsToT = typename GiveQualsTo<T, U>::type;
0125 
0126 // Convenience alias, since size_t integral_constant is used a lot in this file.
0127 template <std::size_t I>
0128 using SizeT = std::integral_constant<std::size_t, I>;
0129 
0130 using NPos = SizeT<variant_npos>;
0131 
0132 template <class Variant, class T, class = void>
0133 struct IndexOfConstructedType {};
0134 
0135 template <std::size_t I, class Variant>
0136 struct VariantAccessResultImpl;
0137 
0138 template <std::size_t I, template <class...> class Variantemplate, class... T>
0139 struct VariantAccessResultImpl<I, Variantemplate<T...>&> {
0140   using type = typename absl::variant_alternative<I, variant<T...>>::type&;
0141 };
0142 
0143 template <std::size_t I, template <class...> class Variantemplate, class... T>
0144 struct VariantAccessResultImpl<I, const Variantemplate<T...>&> {
0145   using type =
0146       const typename absl::variant_alternative<I, variant<T...>>::type&;
0147 };
0148 
0149 template <std::size_t I, template <class...> class Variantemplate, class... T>
0150 struct VariantAccessResultImpl<I, Variantemplate<T...>&&> {
0151   using type = typename absl::variant_alternative<I, variant<T...>>::type&&;
0152 };
0153 
0154 template <std::size_t I, template <class...> class Variantemplate, class... T>
0155 struct VariantAccessResultImpl<I, const Variantemplate<T...>&&> {
0156   using type =
0157       const typename absl::variant_alternative<I, variant<T...>>::type&&;
0158 };
0159 
0160 template <std::size_t I, class Variant>
0161 using VariantAccessResult =
0162     typename VariantAccessResultImpl<I, Variant&&>::type;
0163 
0164 // NOTE: This is used instead of std::array to reduce instantiation overhead.
0165 template <class T, std::size_t Size>
0166 struct SimpleArray {
0167   static_assert(Size != 0, "");
0168   T value[Size];
0169 };
0170 
0171 template <class T>
0172 struct AccessedType {
0173   using type = T;
0174 };
0175 
0176 template <class T>
0177 using AccessedTypeT = typename AccessedType<T>::type;
0178 
0179 template <class T, std::size_t Size>
0180 struct AccessedType<SimpleArray<T, Size>> {
0181   using type = AccessedTypeT<T>;
0182 };
0183 
0184 template <class T>
0185 constexpr T AccessSimpleArray(const T& value) {
0186   return value;
0187 }
0188 
0189 template <class T, std::size_t Size, class... SizeT>
0190 constexpr AccessedTypeT<T> AccessSimpleArray(const SimpleArray<T, Size>& table,
0191                                              std::size_t head_index,
0192                                              SizeT... tail_indices) {
0193   return AccessSimpleArray(table.value[head_index], tail_indices...);
0194 }
0195 
0196 // Note: Intentionally is an alias.
0197 template <class T>
0198 using AlwaysZero = SizeT<0>;
0199 
0200 template <class Op, class... Vs>
0201 struct VisitIndicesResultImpl {
0202   using type = absl::result_of_t<Op(AlwaysZero<Vs>...)>;
0203 };
0204 
0205 template <class Op, class... Vs>
0206 using VisitIndicesResultT = typename VisitIndicesResultImpl<Op, Vs...>::type;
0207 
0208 template <class ReturnType, class FunctionObject, class EndIndices,
0209           class BoundIndices>
0210 struct MakeVisitationMatrix;
0211 
0212 template <class ReturnType, class FunctionObject, std::size_t... Indices>
0213 constexpr ReturnType call_with_indices(FunctionObject&& function) {
0214   static_assert(
0215       std::is_same<ReturnType, decltype(std::declval<FunctionObject>()(
0216                                    SizeT<Indices>()...))>::value,
0217       "Not all visitation overloads have the same return type.");
0218   return std::forward<FunctionObject>(function)(SizeT<Indices>()...);
0219 }
0220 
0221 template <class ReturnType, class FunctionObject, std::size_t... BoundIndices>
0222 struct MakeVisitationMatrix<ReturnType, FunctionObject, index_sequence<>,
0223                             index_sequence<BoundIndices...>> {
0224   using ResultType = ReturnType (*)(FunctionObject&&);
0225   static constexpr ResultType Run() {
0226     return &call_with_indices<ReturnType, FunctionObject,
0227                               (BoundIndices - 1)...>;
0228   }
0229 };
0230 
0231 template <typename Is, std::size_t J>
0232 struct AppendToIndexSequence;
0233 
0234 template <typename Is, std::size_t J>
0235 using AppendToIndexSequenceT = typename AppendToIndexSequence<Is, J>::type;
0236 
0237 template <std::size_t... Is, std::size_t J>
0238 struct AppendToIndexSequence<index_sequence<Is...>, J> {
0239   using type = index_sequence<Is..., J>;
0240 };
0241 
0242 template <class ReturnType, class FunctionObject, class EndIndices,
0243           class CurrIndices, class BoundIndices>
0244 struct MakeVisitationMatrixImpl;
0245 
0246 template <class ReturnType, class FunctionObject, class EndIndices,
0247           std::size_t... CurrIndices, class BoundIndices>
0248 struct MakeVisitationMatrixImpl<ReturnType, FunctionObject, EndIndices,
0249                                 index_sequence<CurrIndices...>, BoundIndices> {
0250   using ResultType = SimpleArray<
0251       typename MakeVisitationMatrix<ReturnType, FunctionObject, EndIndices,
0252                                     index_sequence<>>::ResultType,
0253       sizeof...(CurrIndices)>;
0254 
0255   static constexpr ResultType Run() {
0256     return {{MakeVisitationMatrix<
0257         ReturnType, FunctionObject, EndIndices,
0258         AppendToIndexSequenceT<BoundIndices, CurrIndices>>::Run()...}};
0259   }
0260 };
0261 
0262 template <class ReturnType, class FunctionObject, std::size_t HeadEndIndex,
0263           std::size_t... TailEndIndices, std::size_t... BoundIndices>
0264 struct MakeVisitationMatrix<ReturnType, FunctionObject,
0265                             index_sequence<HeadEndIndex, TailEndIndices...>,
0266                             index_sequence<BoundIndices...>>
0267     : MakeVisitationMatrixImpl<ReturnType, FunctionObject,
0268                                index_sequence<TailEndIndices...>,
0269                                absl::make_index_sequence<HeadEndIndex>,
0270                                index_sequence<BoundIndices...>> {};
0271 
0272 struct UnreachableSwitchCase {
0273   template <class Op>
0274   [[noreturn]] static VisitIndicesResultT<Op, std::size_t> Run(
0275       Op&& /*ignored*/) {
0276     ABSL_UNREACHABLE();
0277   }
0278 };
0279 
0280 template <class Op, std::size_t I>
0281 struct ReachableSwitchCase {
0282   static VisitIndicesResultT<Op, std::size_t> Run(Op&& op) {
0283     return absl::base_internal::invoke(std::forward<Op>(op), SizeT<I>());
0284   }
0285 };
0286 
0287 // The number 33 is just a guess at a reasonable maximum to our switch. It is
0288 // not based on any analysis. The reason it is a power of 2 plus 1 instead of a
0289 // power of 2 is because the number was picked to correspond to a power of 2
0290 // amount of "normal" alternatives, plus one for the possibility of the user
0291 // providing "monostate" in addition to the more natural alternatives.
0292 ABSL_INTERNAL_INLINE_CONSTEXPR(std::size_t, MaxUnrolledVisitCases, 33);
0293 
0294 // Note: The default-definition is for unreachable cases.
0295 template <bool IsReachable>
0296 struct PickCaseImpl {
0297   template <class Op, std::size_t I>
0298   using Apply = UnreachableSwitchCase;
0299 };
0300 
0301 template <>
0302 struct PickCaseImpl</*IsReachable =*/true> {
0303   template <class Op, std::size_t I>
0304   using Apply = ReachableSwitchCase<Op, I>;
0305 };
0306 
0307 // Note: This form of dance with template aliases is to make sure that we
0308 //       instantiate a number of templates proportional to the number of variant
0309 //       alternatives rather than a number of templates proportional to our
0310 //       maximum unrolled amount of visitation cases (aliases are effectively
0311 //       "free" whereas other template instantiations are costly).
0312 template <class Op, std::size_t I, std::size_t EndIndex>
0313 using PickCase = typename PickCaseImpl<(I < EndIndex)>::template Apply<Op, I>;
0314 
0315 template <class ReturnType>
0316 [[noreturn]] ReturnType TypedThrowBadVariantAccess() {
0317   absl::variant_internal::ThrowBadVariantAccess();
0318 }
0319 
0320 // Given N variant sizes, determine the number of cases there would need to be
0321 // in a single switch-statement that would cover every possibility in the
0322 // corresponding N-ary visit operation.
0323 template <std::size_t... NumAlternatives>
0324 struct NumCasesOfSwitch;
0325 
0326 template <std::size_t HeadNumAlternatives, std::size_t... TailNumAlternatives>
0327 struct NumCasesOfSwitch<HeadNumAlternatives, TailNumAlternatives...> {
0328   static constexpr std::size_t value =
0329       (HeadNumAlternatives + 1) *
0330       NumCasesOfSwitch<TailNumAlternatives...>::value;
0331 };
0332 
0333 template <>
0334 struct NumCasesOfSwitch<> {
0335   static constexpr std::size_t value = 1;
0336 };
0337 
0338 // A switch statement optimizes better than the table of function pointers.
0339 template <std::size_t EndIndex>
0340 struct VisitIndicesSwitch {
0341   static_assert(EndIndex <= MaxUnrolledVisitCases,
0342                 "Maximum unrolled switch size exceeded.");
0343 
0344   template <class Op>
0345   static VisitIndicesResultT<Op, std::size_t> Run(Op&& op, std::size_t i) {
0346     switch (i) {
0347       case 0:
0348         return PickCase<Op, 0, EndIndex>::Run(std::forward<Op>(op));
0349       case 1:
0350         return PickCase<Op, 1, EndIndex>::Run(std::forward<Op>(op));
0351       case 2:
0352         return PickCase<Op, 2, EndIndex>::Run(std::forward<Op>(op));
0353       case 3:
0354         return PickCase<Op, 3, EndIndex>::Run(std::forward<Op>(op));
0355       case 4:
0356         return PickCase<Op, 4, EndIndex>::Run(std::forward<Op>(op));
0357       case 5:
0358         return PickCase<Op, 5, EndIndex>::Run(std::forward<Op>(op));
0359       case 6:
0360         return PickCase<Op, 6, EndIndex>::Run(std::forward<Op>(op));
0361       case 7:
0362         return PickCase<Op, 7, EndIndex>::Run(std::forward<Op>(op));
0363       case 8:
0364         return PickCase<Op, 8, EndIndex>::Run(std::forward<Op>(op));
0365       case 9:
0366         return PickCase<Op, 9, EndIndex>::Run(std::forward<Op>(op));
0367       case 10:
0368         return PickCase<Op, 10, EndIndex>::Run(std::forward<Op>(op));
0369       case 11:
0370         return PickCase<Op, 11, EndIndex>::Run(std::forward<Op>(op));
0371       case 12:
0372         return PickCase<Op, 12, EndIndex>::Run(std::forward<Op>(op));
0373       case 13:
0374         return PickCase<Op, 13, EndIndex>::Run(std::forward<Op>(op));
0375       case 14:
0376         return PickCase<Op, 14, EndIndex>::Run(std::forward<Op>(op));
0377       case 15:
0378         return PickCase<Op, 15, EndIndex>::Run(std::forward<Op>(op));
0379       case 16:
0380         return PickCase<Op, 16, EndIndex>::Run(std::forward<Op>(op));
0381       case 17:
0382         return PickCase<Op, 17, EndIndex>::Run(std::forward<Op>(op));
0383       case 18:
0384         return PickCase<Op, 18, EndIndex>::Run(std::forward<Op>(op));
0385       case 19:
0386         return PickCase<Op, 19, EndIndex>::Run(std::forward<Op>(op));
0387       case 20:
0388         return PickCase<Op, 20, EndIndex>::Run(std::forward<Op>(op));
0389       case 21:
0390         return PickCase<Op, 21, EndIndex>::Run(std::forward<Op>(op));
0391       case 22:
0392         return PickCase<Op, 22, EndIndex>::Run(std::forward<Op>(op));
0393       case 23:
0394         return PickCase<Op, 23, EndIndex>::Run(std::forward<Op>(op));
0395       case 24:
0396         return PickCase<Op, 24, EndIndex>::Run(std::forward<Op>(op));
0397       case 25:
0398         return PickCase<Op, 25, EndIndex>::Run(std::forward<Op>(op));
0399       case 26:
0400         return PickCase<Op, 26, EndIndex>::Run(std::forward<Op>(op));
0401       case 27:
0402         return PickCase<Op, 27, EndIndex>::Run(std::forward<Op>(op));
0403       case 28:
0404         return PickCase<Op, 28, EndIndex>::Run(std::forward<Op>(op));
0405       case 29:
0406         return PickCase<Op, 29, EndIndex>::Run(std::forward<Op>(op));
0407       case 30:
0408         return PickCase<Op, 30, EndIndex>::Run(std::forward<Op>(op));
0409       case 31:
0410         return PickCase<Op, 31, EndIndex>::Run(std::forward<Op>(op));
0411       case 32:
0412         return PickCase<Op, 32, EndIndex>::Run(std::forward<Op>(op));
0413       default:
0414         ABSL_ASSERT(i == variant_npos);
0415         return absl::base_internal::invoke(std::forward<Op>(op), NPos());
0416     }
0417   }
0418 };
0419 
0420 template <std::size_t... EndIndices>
0421 struct VisitIndicesFallback {
0422   template <class Op, class... SizeT>
0423   static VisitIndicesResultT<Op, SizeT...> Run(Op&& op, SizeT... indices) {
0424     return AccessSimpleArray(
0425         MakeVisitationMatrix<VisitIndicesResultT<Op, SizeT...>, Op,
0426                              index_sequence<(EndIndices + 1)...>,
0427                              index_sequence<>>::Run(),
0428         (indices + 1)...)(std::forward<Op>(op));
0429   }
0430 };
0431 
0432 // Take an N-dimensional series of indices and convert them into a single index
0433 // without loss of information. The purpose of this is to be able to convert an
0434 // N-ary visit operation into a single switch statement.
0435 template <std::size_t...>
0436 struct FlattenIndices;
0437 
0438 template <std::size_t HeadSize, std::size_t... TailSize>
0439 struct FlattenIndices<HeadSize, TailSize...> {
0440   template <class... SizeType>
0441   static constexpr std::size_t Run(std::size_t head, SizeType... tail) {
0442     return head + HeadSize * FlattenIndices<TailSize...>::Run(tail...);
0443   }
0444 };
0445 
0446 template <>
0447 struct FlattenIndices<> {
0448   static constexpr std::size_t Run() { return 0; }
0449 };
0450 
0451 // Take a single "flattened" index (flattened by FlattenIndices) and determine
0452 // the value of the index of one of the logically represented dimensions.
0453 template <std::size_t I, std::size_t IndexToGet, std::size_t HeadSize,
0454           std::size_t... TailSize>
0455 struct UnflattenIndex {
0456   static constexpr std::size_t value =
0457       UnflattenIndex<I / HeadSize, IndexToGet - 1, TailSize...>::value;
0458 };
0459 
0460 template <std::size_t I, std::size_t HeadSize, std::size_t... TailSize>
0461 struct UnflattenIndex<I, 0, HeadSize, TailSize...> {
0462   static constexpr std::size_t value = (I % HeadSize);
0463 };
0464 
0465 // The backend for converting an N-ary visit operation into a unary visit.
0466 template <class IndexSequence, std::size_t... EndIndices>
0467 struct VisitIndicesVariadicImpl;
0468 
0469 template <std::size_t... N, std::size_t... EndIndices>
0470 struct VisitIndicesVariadicImpl<absl::index_sequence<N...>, EndIndices...> {
0471   // A type that can take an N-ary function object and converts it to a unary
0472   // function object that takes a single, flattened index, and "unflattens" it
0473   // into its individual dimensions when forwarding to the wrapped object.
0474   template <class Op>
0475   struct FlattenedOp {
0476     template <std::size_t I>
0477     VisitIndicesResultT<Op, decltype(EndIndices)...> operator()(
0478         SizeT<I> /*index*/) && {
0479       return base_internal::invoke(
0480           std::forward<Op>(op),
0481           SizeT<UnflattenIndex<I, N, (EndIndices + 1)...>::value -
0482                 std::size_t{1}>()...);
0483     }
0484 
0485     Op&& op;
0486   };
0487 
0488   template <class Op, class... SizeType>
0489   static VisitIndicesResultT<Op, decltype(EndIndices)...> Run(Op&& op,
0490                                                               SizeType... i) {
0491     return VisitIndicesSwitch<NumCasesOfSwitch<EndIndices...>::value>::Run(
0492         FlattenedOp<Op>{std::forward<Op>(op)},
0493         FlattenIndices<(EndIndices + std::size_t{1})...>::Run(
0494             (i + std::size_t{1})...));
0495   }
0496 };
0497 
0498 template <std::size_t... EndIndices>
0499 struct VisitIndicesVariadic
0500     : VisitIndicesVariadicImpl<absl::make_index_sequence<sizeof...(EndIndices)>,
0501                                EndIndices...> {};
0502 
0503 // This implementation will flatten N-ary visit operations into a single switch
0504 // statement when the number of cases would be less than our maximum specified
0505 // switch-statement size.
0506 // TODO(calabrese)
0507 //   Based on benchmarks, determine whether the function table approach actually
0508 //   does optimize better than a chain of switch statements and possibly update
0509 //   the implementation accordingly. Also consider increasing the maximum switch
0510 //   size.
0511 template <std::size_t... EndIndices>
0512 struct VisitIndices
0513     : absl::conditional_t<(NumCasesOfSwitch<EndIndices...>::value <=
0514                            MaxUnrolledVisitCases),
0515                           VisitIndicesVariadic<EndIndices...>,
0516                           VisitIndicesFallback<EndIndices...>> {};
0517 
0518 template <std::size_t EndIndex>
0519 struct VisitIndices<EndIndex>
0520     : absl::conditional_t<(EndIndex <= MaxUnrolledVisitCases),
0521                           VisitIndicesSwitch<EndIndex>,
0522                           VisitIndicesFallback<EndIndex>> {};
0523 
0524 // Suppress bogus warning on MSVC: MSVC complains that the `reinterpret_cast`
0525 // below is returning the address of a temporary or local object.
0526 #ifdef _MSC_VER
0527 #pragma warning(push)
0528 #pragma warning(disable : 4172)
0529 #endif  // _MSC_VER
0530 
0531 // TODO(calabrese) std::launder
0532 // TODO(calabrese) constexpr
0533 // NOTE: DO NOT REMOVE the `inline` keyword as it is necessary to work around a
0534 // MSVC bug. See https://github.com/abseil/abseil-cpp/issues/129 for details.
0535 template <class Self, std::size_t I>
0536 inline VariantAccessResult<I, Self> AccessUnion(Self&& self, SizeT<I> /*i*/) {
0537   return reinterpret_cast<VariantAccessResult<I, Self>>(self);
0538 }
0539 
0540 #ifdef _MSC_VER
0541 #pragma warning(pop)
0542 #endif  // _MSC_VER
0543 
0544 template <class T>
0545 void DeducedDestroy(T& self) {  // NOLINT
0546   self.~T();
0547 }
0548 
0549 // NOTE: This type exists as a single entity for variant and its bases to
0550 // befriend. It contains helper functionality that manipulates the state of the
0551 // variant, such as the implementation of things like assignment and emplace
0552 // operations.
0553 struct VariantCoreAccess {
0554   template <class VariantType>
0555   static typename VariantType::Variant& Derived(VariantType& self) {  // NOLINT
0556     return static_cast<typename VariantType::Variant&>(self);
0557   }
0558 
0559   template <class VariantType>
0560   static const typename VariantType::Variant& Derived(
0561       const VariantType& self) {  // NOLINT
0562     return static_cast<const typename VariantType::Variant&>(self);
0563   }
0564 
0565   template <class VariantType>
0566   static void Destroy(VariantType& self) {  // NOLINT
0567     Derived(self).destroy();
0568     self.index_ = absl::variant_npos;
0569   }
0570 
0571   template <class Variant>
0572   static void SetIndex(Variant& self, std::size_t i) {  // NOLINT
0573     self.index_ = i;
0574   }
0575 
0576   template <class Variant>
0577   static void InitFrom(Variant& self, Variant&& other) {  // NOLINT
0578     VisitIndices<absl::variant_size<Variant>::value>::Run(
0579         InitFromVisitor<Variant, Variant&&>{&self,
0580                                             std::forward<Variant>(other)},
0581         other.index());
0582     self.index_ = other.index();
0583   }
0584 
0585   // Access a variant alternative, assuming the index is correct.
0586   template <std::size_t I, class Variant>
0587   static VariantAccessResult<I, Variant> Access(Variant&& self) {
0588     // This cast instead of invocation of AccessUnion with an rvalue is a
0589     // workaround for msvc. Without this there is a runtime failure when dealing
0590     // with rvalues.
0591     // TODO(calabrese) Reduce test case and find a simpler workaround.
0592     return static_cast<VariantAccessResult<I, Variant>>(
0593         variant_internal::AccessUnion(self.state_, SizeT<I>()));
0594   }
0595 
0596   // Access a variant alternative, throwing if the index is incorrect.
0597   template <std::size_t I, class Variant>
0598   static VariantAccessResult<I, Variant> CheckedAccess(Variant&& self) {
0599     if (ABSL_PREDICT_FALSE(self.index_ != I)) {
0600       TypedThrowBadVariantAccess<VariantAccessResult<I, Variant>>();
0601     }
0602 
0603     return Access<I>(std::forward<Variant>(self));
0604   }
0605 
0606   // The implementation of the move-assignment operation for a variant.
0607   template <class VType>
0608   struct MoveAssignVisitor {
0609     using DerivedType = typename VType::Variant;
0610     template <std::size_t NewIndex>
0611     void operator()(SizeT<NewIndex> /*new_i*/) const {
0612       if (left->index_ == NewIndex) {
0613         Access<NewIndex>(*left) = std::move(Access<NewIndex>(*right));
0614       } else {
0615         Derived(*left).template emplace<NewIndex>(
0616             std::move(Access<NewIndex>(*right)));
0617       }
0618     }
0619 
0620     void operator()(SizeT<absl::variant_npos> /*new_i*/) const {
0621       Destroy(*left);
0622     }
0623 
0624     VType* left;
0625     VType* right;
0626   };
0627 
0628   template <class VType>
0629   static MoveAssignVisitor<VType> MakeMoveAssignVisitor(VType* left,
0630                                                         VType* other) {
0631     return {left, other};
0632   }
0633 
0634   // The implementation of the assignment operation for a variant.
0635   template <class VType>
0636   struct CopyAssignVisitor {
0637     using DerivedType = typename VType::Variant;
0638     template <std::size_t NewIndex>
0639     void operator()(SizeT<NewIndex> /*new_i*/) const {
0640       using New =
0641           typename absl::variant_alternative<NewIndex, DerivedType>::type;
0642 
0643       if (left->index_ == NewIndex) {
0644         Access<NewIndex>(*left) = Access<NewIndex>(*right);
0645       } else if (std::is_nothrow_copy_constructible<New>::value ||
0646                  !std::is_nothrow_move_constructible<New>::value) {
0647         Derived(*left).template emplace<NewIndex>(Access<NewIndex>(*right));
0648       } else {
0649         Derived(*left) = DerivedType(Derived(*right));
0650       }
0651     }
0652 
0653     void operator()(SizeT<absl::variant_npos> /*new_i*/) const {
0654       Destroy(*left);
0655     }
0656 
0657     VType* left;
0658     const VType* right;
0659   };
0660 
0661   template <class VType>
0662   static CopyAssignVisitor<VType> MakeCopyAssignVisitor(VType* left,
0663                                                         const VType& other) {
0664     return {left, &other};
0665   }
0666 
0667   // The implementation of conversion-assignment operations for variant.
0668   template <class Left, class QualifiedNew>
0669   struct ConversionAssignVisitor {
0670     using NewIndex =
0671         variant_internal::IndexOfConstructedType<Left, QualifiedNew>;
0672 
0673     void operator()(SizeT<NewIndex::value> /*old_i*/
0674     ) const {
0675       Access<NewIndex::value>(*left) = std::forward<QualifiedNew>(other);
0676     }
0677 
0678     template <std::size_t OldIndex>
0679     void operator()(SizeT<OldIndex> /*old_i*/
0680     ) const {
0681       using New =
0682           typename absl::variant_alternative<NewIndex::value, Left>::type;
0683       if (std::is_nothrow_constructible<New, QualifiedNew>::value ||
0684           !std::is_nothrow_move_constructible<New>::value) {
0685         left->template emplace<NewIndex::value>(
0686             std::forward<QualifiedNew>(other));
0687       } else {
0688         // the standard says "equivalent to
0689         // operator=(variant(std::forward<T>(t)))", but we use `emplace` here
0690         // because the variant's move assignment operator could be deleted.
0691         left->template emplace<NewIndex::value>(
0692             New(std::forward<QualifiedNew>(other)));
0693       }
0694     }
0695 
0696     Left* left;
0697     QualifiedNew&& other;
0698   };
0699 
0700   template <class Left, class QualifiedNew>
0701   static ConversionAssignVisitor<Left, QualifiedNew>
0702   MakeConversionAssignVisitor(Left* left, QualifiedNew&& qual) {
0703     return {left, std::forward<QualifiedNew>(qual)};
0704   }
0705 
0706   // Backend for operations for `emplace()` which destructs `*self` then
0707   // construct a new alternative with `Args...`.
0708   template <std::size_t NewIndex, class Self, class... Args>
0709   static typename absl::variant_alternative<NewIndex, Self>::type& Replace(
0710       Self* self, Args&&... args) {
0711     Destroy(*self);
0712     using New = typename absl::variant_alternative<NewIndex, Self>::type;
0713     New* const result = ::new (static_cast<void*>(&self->state_))
0714         New(std::forward<Args>(args)...);
0715     self->index_ = NewIndex;
0716     return *result;
0717   }
0718 
0719   template <class LeftVariant, class QualifiedRightVariant>
0720   struct InitFromVisitor {
0721     template <std::size_t NewIndex>
0722     void operator()(SizeT<NewIndex> /*new_i*/) const {
0723       using Alternative =
0724           typename variant_alternative<NewIndex, LeftVariant>::type;
0725       ::new (static_cast<void*>(&left->state_)) Alternative(
0726           Access<NewIndex>(std::forward<QualifiedRightVariant>(right)));
0727     }
0728 
0729     void operator()(SizeT<absl::variant_npos> /*new_i*/) const {
0730       // This space intentionally left blank.
0731     }
0732     LeftVariant* left;
0733     QualifiedRightVariant&& right;
0734   };
0735 };
0736 
0737 template <class Expected, class... T>
0738 struct IndexOfImpl;
0739 
0740 template <class Expected>
0741 struct IndexOfImpl<Expected> {
0742   using IndexFromEnd = SizeT<0>;
0743   using MatchedIndexFromEnd = IndexFromEnd;
0744   using MultipleMatches = std::false_type;
0745 };
0746 
0747 template <class Expected, class Head, class... Tail>
0748 struct IndexOfImpl<Expected, Head, Tail...> : IndexOfImpl<Expected, Tail...> {
0749   using IndexFromEnd =
0750       SizeT<IndexOfImpl<Expected, Tail...>::IndexFromEnd::value + 1>;
0751 };
0752 
0753 template <class Expected, class... Tail>
0754 struct IndexOfImpl<Expected, Expected, Tail...>
0755     : IndexOfImpl<Expected, Tail...> {
0756   using IndexFromEnd =
0757       SizeT<IndexOfImpl<Expected, Tail...>::IndexFromEnd::value + 1>;
0758   using MatchedIndexFromEnd = IndexFromEnd;
0759   using MultipleMatches = std::integral_constant<
0760       bool, IndexOfImpl<Expected, Tail...>::MatchedIndexFromEnd::value != 0>;
0761 };
0762 
0763 template <class Expected, class... Types>
0764 struct IndexOfMeta {
0765   using Results = IndexOfImpl<Expected, Types...>;
0766   static_assert(!Results::MultipleMatches::value,
0767                 "Attempted to access a variant by specifying a type that "
0768                 "matches more than one alternative.");
0769   static_assert(Results::MatchedIndexFromEnd::value != 0,
0770                 "Attempted to access a variant by specifying a type that does "
0771                 "not match any alternative.");
0772   using type = SizeT<sizeof...(Types) - Results::MatchedIndexFromEnd::value>;
0773 };
0774 
0775 template <class Expected, class... Types>
0776 using IndexOf = typename IndexOfMeta<Expected, Types...>::type;
0777 
0778 template <class Variant, class T, std::size_t CurrIndex>
0779 struct UnambiguousIndexOfImpl;
0780 
0781 // Terminating case encountered once we've checked all of the alternatives
0782 template <class T, std::size_t CurrIndex>
0783 struct UnambiguousIndexOfImpl<variant<>, T, CurrIndex> : SizeT<CurrIndex> {};
0784 
0785 // Case where T is not Head
0786 template <class Head, class... Tail, class T, std::size_t CurrIndex>
0787 struct UnambiguousIndexOfImpl<variant<Head, Tail...>, T, CurrIndex>
0788     : UnambiguousIndexOfImpl<variant<Tail...>, T, CurrIndex + 1>::type {};
0789 
0790 // Case where T is Head
0791 template <class Head, class... Tail, std::size_t CurrIndex>
0792 struct UnambiguousIndexOfImpl<variant<Head, Tail...>, Head, CurrIndex>
0793     : SizeT<UnambiguousIndexOfImpl<variant<Tail...>, Head, 0>::value ==
0794                     sizeof...(Tail)
0795                 ? CurrIndex
0796                 : CurrIndex + sizeof...(Tail) + 1> {};
0797 
0798 template <class Variant, class T>
0799 struct UnambiguousIndexOf;
0800 
0801 struct NoMatch {
0802   struct type {};
0803 };
0804 
0805 template <class... Alts, class T>
0806 struct UnambiguousIndexOf<variant<Alts...>, T>
0807     : std::conditional<UnambiguousIndexOfImpl<variant<Alts...>, T, 0>::value !=
0808                            sizeof...(Alts),
0809                        UnambiguousIndexOfImpl<variant<Alts...>, T, 0>,
0810                        NoMatch>::type::type {};
0811 
0812 template <class T, std::size_t /*Dummy*/>
0813 using UnambiguousTypeOfImpl = T;
0814 
0815 template <class Variant, class T>
0816 using UnambiguousTypeOfT =
0817     UnambiguousTypeOfImpl<T, UnambiguousIndexOf<Variant, T>::value>;
0818 
0819 template <class H, class... T>
0820 class VariantStateBase;
0821 
0822 // This is an implementation of the "imaginary function" that is described in
0823 // [variant.ctor]
0824 // It is used in order to determine which alternative to construct during
0825 // initialization from some type T.
0826 template <class Variant, std::size_t I = 0>
0827 struct ImaginaryFun;
0828 
0829 template <std::size_t I>
0830 struct ImaginaryFun<variant<>, I> {
0831   static void Run() = delete;
0832 };
0833 
0834 template <class H, class... T, std::size_t I>
0835 struct ImaginaryFun<variant<H, T...>, I> : ImaginaryFun<variant<T...>, I + 1> {
0836   using ImaginaryFun<variant<T...>, I + 1>::Run;
0837 
0838   // NOTE: const& and && are used instead of by-value due to lack of guaranteed
0839   // move elision of C++17. This may have other minor differences, but tests
0840   // pass.
0841   static SizeT<I> Run(const H&, SizeT<I>);
0842   static SizeT<I> Run(H&&, SizeT<I>);
0843 };
0844 
0845 // The following metafunctions are used in constructor and assignment
0846 // constraints.
0847 template <class Self, class T>
0848 struct IsNeitherSelfNorInPlace : std::true_type {};
0849 
0850 template <class Self>
0851 struct IsNeitherSelfNorInPlace<Self, Self> : std::false_type {};
0852 
0853 template <class Self, class T>
0854 struct IsNeitherSelfNorInPlace<Self, in_place_type_t<T>> : std::false_type {};
0855 
0856 template <class Self, std::size_t I>
0857 struct IsNeitherSelfNorInPlace<Self, in_place_index_t<I>> : std::false_type {};
0858 
0859 template <class Variant, class T>
0860 struct IndexOfConstructedType<
0861     Variant, T,
0862     void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {}))>>
0863     : decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {})) {};
0864 
0865 template <std::size_t... Is>
0866 struct ContainsVariantNPos
0867     : absl::negation<std::is_same<  // NOLINT
0868           std::integer_sequence<bool, 0 <= Is...>,
0869           std::integer_sequence<bool, Is != absl::variant_npos...>>> {};
0870 
0871 template <class Op, class... QualifiedVariants>
0872 using RawVisitResult =
0873     absl::result_of_t<Op(VariantAccessResult<0, QualifiedVariants>...)>;
0874 
0875 // NOTE: The spec requires that all return-paths yield the same type and is not
0876 // SFINAE-friendly, so we can deduce the return type by examining the first
0877 // result. If it's not callable, then we get an error, but are compliant and
0878 // fast to compile.
0879 // TODO(calabrese) Possibly rewrite in a way that yields better compile errors
0880 // at the cost of longer compile-times.
0881 template <class Op, class... QualifiedVariants>
0882 struct VisitResultImpl {
0883   using type =
0884       absl::result_of_t<Op(VariantAccessResult<0, QualifiedVariants>...)>;
0885 };
0886 
0887 // Done in two steps intentionally so that we don't cause substitution to fail.
0888 template <class Op, class... QualifiedVariants>
0889 using VisitResult = typename VisitResultImpl<Op, QualifiedVariants...>::type;
0890 
0891 template <class Op, class... QualifiedVariants>
0892 struct PerformVisitation {
0893   using ReturnType = VisitResult<Op, QualifiedVariants...>;
0894 
0895   template <std::size_t... Is>
0896   constexpr ReturnType operator()(SizeT<Is>... indices) const {
0897     return Run(typename ContainsVariantNPos<Is...>::type{},
0898                absl::index_sequence_for<QualifiedVariants...>(), indices...);
0899   }
0900 
0901   template <std::size_t... TupIs, std::size_t... Is>
0902   constexpr ReturnType Run(std::false_type /*has_valueless*/,
0903                            index_sequence<TupIs...>, SizeT<Is>...) const {
0904     static_assert(
0905         std::is_same<ReturnType,
0906                      absl::result_of_t<Op(VariantAccessResult<
0907                                           Is, QualifiedVariants>...)>>::value,
0908         "All visitation overloads must have the same return type.");
0909     return absl::base_internal::invoke(
0910         std::forward<Op>(op),
0911         VariantCoreAccess::Access<Is>(
0912             std::forward<QualifiedVariants>(std::get<TupIs>(variant_tup)))...);
0913   }
0914 
0915   template <std::size_t... TupIs, std::size_t... Is>
0916   [[noreturn]] ReturnType Run(std::true_type /*has_valueless*/,
0917                               index_sequence<TupIs...>, SizeT<Is>...) const {
0918     absl::variant_internal::ThrowBadVariantAccess();
0919   }
0920 
0921   // TODO(calabrese) Avoid using a tuple, which causes lots of instantiations
0922   // Attempts using lambda variadic captures fail on current GCC.
0923   std::tuple<QualifiedVariants&&...> variant_tup;
0924   Op&& op;
0925 };
0926 
0927 template <class... T>
0928 union Union;
0929 
0930 // We want to allow for variant<> to be trivial. For that, we need the default
0931 // constructor to be trivial, which means we can't define it ourselves.
0932 // Instead, we use a non-default constructor that takes NoopConstructorTag
0933 // that doesn't affect the triviality of the types.
0934 struct NoopConstructorTag {};
0935 
0936 template <std::size_t I>
0937 struct EmplaceTag {};
0938 
0939 template <>
0940 union Union<> {
0941   constexpr explicit Union(NoopConstructorTag) noexcept {}
0942 };
0943 
0944 // Suppress bogus warning on MSVC: MSVC complains that Union<T...> has a defined
0945 // deleted destructor from the `std::is_destructible` check below.
0946 #ifdef _MSC_VER
0947 #pragma warning(push)
0948 #pragma warning(disable : 4624)
0949 #endif  // _MSC_VER
0950 
0951 template <class Head, class... Tail>
0952 union Union<Head, Tail...> {
0953   using TailUnion = Union<Tail...>;
0954 
0955   explicit constexpr Union(NoopConstructorTag /*tag*/) noexcept
0956       : tail(NoopConstructorTag()) {}
0957 
0958   template <class... P>
0959   explicit constexpr Union(EmplaceTag<0>, P&&... args)
0960       : head(std::forward<P>(args)...) {}
0961 
0962   template <std::size_t I, class... P>
0963   explicit constexpr Union(EmplaceTag<I>, P&&... args)
0964       : tail(EmplaceTag<I - 1>{}, std::forward<P>(args)...) {}
0965 
0966   Head head;
0967   TailUnion tail;
0968 };
0969 
0970 #ifdef _MSC_VER
0971 #pragma warning(pop)
0972 #endif  // _MSC_VER
0973 
0974 // TODO(calabrese) Just contain a Union in this union (certain configs fail).
0975 template <class... T>
0976 union DestructibleUnionImpl;
0977 
0978 template <>
0979 union DestructibleUnionImpl<> {
0980   constexpr explicit DestructibleUnionImpl(NoopConstructorTag) noexcept {}
0981 };
0982 
0983 template <class Head, class... Tail>
0984 union DestructibleUnionImpl<Head, Tail...> {
0985   using TailUnion = DestructibleUnionImpl<Tail...>;
0986 
0987   explicit constexpr DestructibleUnionImpl(NoopConstructorTag /*tag*/) noexcept
0988       : tail(NoopConstructorTag()) {}
0989 
0990   template <class... P>
0991   explicit constexpr DestructibleUnionImpl(EmplaceTag<0>, P&&... args)
0992       : head(std::forward<P>(args)...) {}
0993 
0994   template <std::size_t I, class... P>
0995   explicit constexpr DestructibleUnionImpl(EmplaceTag<I>, P&&... args)
0996       : tail(EmplaceTag<I - 1>{}, std::forward<P>(args)...) {}
0997 
0998   ~DestructibleUnionImpl() {}
0999 
1000   Head head;
1001   TailUnion tail;
1002 };
1003 
1004 // This union type is destructible even if one or more T are not trivially
1005 // destructible. In the case that all T are trivially destructible, then so is
1006 // this resultant type.
1007 template <class... T>
1008 using DestructibleUnion =
1009     absl::conditional_t<std::is_destructible<Union<T...>>::value, Union<T...>,
1010                         DestructibleUnionImpl<T...>>;
1011 
1012 // Deepest base, containing the actual union and the discriminator
1013 template <class H, class... T>
1014 class VariantStateBase {
1015  protected:
1016   using Variant = variant<H, T...>;
1017 
1018   template <class LazyH = H,
1019             class ConstructibleH = absl::enable_if_t<
1020                 std::is_default_constructible<LazyH>::value, LazyH>>
1021   constexpr VariantStateBase() noexcept(
1022       std::is_nothrow_default_constructible<ConstructibleH>::value)
1023       : state_(EmplaceTag<0>()), index_(0) {}
1024 
1025   template <std::size_t I, class... P>
1026   explicit constexpr VariantStateBase(EmplaceTag<I> tag, P&&... args)
1027       : state_(tag, std::forward<P>(args)...), index_(I) {}
1028 
1029   explicit constexpr VariantStateBase(NoopConstructorTag)
1030       : state_(NoopConstructorTag()), index_(variant_npos) {}
1031 
1032   void destroy() {}  // Does nothing (shadowed in child if non-trivial)
1033 
1034   DestructibleUnion<H, T...> state_;
1035   std::size_t index_;
1036 };
1037 
1038 using absl::internal::type_identity;
1039 
1040 // OverloadSet::Overload() is a unary function which is overloaded to
1041 // take any of the element types of the variant, by reference-to-const.
1042 // The return type of the overload on T is type_identity<T>, so that you
1043 // can statically determine which overload was called.
1044 //
1045 // Overload() is not defined, so it can only be called in unevaluated
1046 // contexts.
1047 template <typename... Ts>
1048 struct OverloadSet;
1049 
1050 template <typename T, typename... Ts>
1051 struct OverloadSet<T, Ts...> : OverloadSet<Ts...> {
1052   using Base = OverloadSet<Ts...>;
1053   static type_identity<T> Overload(const T&);
1054   using Base::Overload;
1055 };
1056 
1057 template <>
1058 struct OverloadSet<> {
1059   // For any case not handled above.
1060   static void Overload(...);
1061 };
1062 
1063 template <class T>
1064 using LessThanResult = decltype(std::declval<T>() < std::declval<T>());
1065 
1066 template <class T>
1067 using GreaterThanResult = decltype(std::declval<T>() > std::declval<T>());
1068 
1069 template <class T>
1070 using LessThanOrEqualResult = decltype(std::declval<T>() <= std::declval<T>());
1071 
1072 template <class T>
1073 using GreaterThanOrEqualResult =
1074     decltype(std::declval<T>() >= std::declval<T>());
1075 
1076 template <class T>
1077 using EqualResult = decltype(std::declval<T>() == std::declval<T>());
1078 
1079 template <class T>
1080 using NotEqualResult = decltype(std::declval<T>() != std::declval<T>());
1081 
1082 using type_traits_internal::is_detected_convertible;
1083 
1084 template <class... T>
1085 using RequireAllHaveEqualT = absl::enable_if_t<
1086     absl::conjunction<is_detected_convertible<bool, EqualResult, T>...>::value,
1087     bool>;
1088 
1089 template <class... T>
1090 using RequireAllHaveNotEqualT =
1091     absl::enable_if_t<absl::conjunction<is_detected_convertible<
1092                           bool, NotEqualResult, T>...>::value,
1093                       bool>;
1094 
1095 template <class... T>
1096 using RequireAllHaveLessThanT =
1097     absl::enable_if_t<absl::conjunction<is_detected_convertible<
1098                           bool, LessThanResult, T>...>::value,
1099                       bool>;
1100 
1101 template <class... T>
1102 using RequireAllHaveLessThanOrEqualT =
1103     absl::enable_if_t<absl::conjunction<is_detected_convertible<
1104                           bool, LessThanOrEqualResult, T>...>::value,
1105                       bool>;
1106 
1107 template <class... T>
1108 using RequireAllHaveGreaterThanOrEqualT =
1109     absl::enable_if_t<absl::conjunction<is_detected_convertible<
1110                           bool, GreaterThanOrEqualResult, T>...>::value,
1111                       bool>;
1112 
1113 template <class... T>
1114 using RequireAllHaveGreaterThanT =
1115     absl::enable_if_t<absl::conjunction<is_detected_convertible<
1116                           bool, GreaterThanResult, T>...>::value,
1117                       bool>;
1118 
1119 // Helper template containing implementations details of variant that can't go
1120 // in the private section. For convenience, this takes the variant type as a
1121 // single template parameter.
1122 template <typename T>
1123 struct VariantHelper;
1124 
1125 template <typename... Ts>
1126 struct VariantHelper<variant<Ts...>> {
1127   // Type metafunction which returns the element type selected if
1128   // OverloadSet::Overload() is well-formed when called with argument type U.
1129   template <typename U>
1130   using BestMatch = decltype(variant_internal::OverloadSet<Ts...>::Overload(
1131       std::declval<U>()));
1132 
1133   // Type metafunction which returns true if OverloadSet::Overload() is
1134   // well-formed when called with argument type U.
1135   // CanAccept can't be just an alias because there is a MSVC bug on parameter
1136   // pack expansion involving decltype.
1137   template <typename U>
1138   struct CanAccept
1139       : std::integral_constant<bool, !std::is_void<BestMatch<U>>::value> {};
1140 
1141   // Type metafunction which returns true if Other is an instantiation of
1142   // variant, and variants's converting constructor from Other will be
1143   // well-formed. We will use this to remove constructors that would be
1144   // ill-formed from the overload set.
1145   template <typename Other>
1146   struct CanConvertFrom;
1147 
1148   template <typename... Us>
1149   struct CanConvertFrom<variant<Us...>>
1150       : public absl::conjunction<CanAccept<Us>...> {};
1151 };
1152 
1153 // A type with nontrivial copy ctor and trivial move ctor.
1154 struct TrivialMoveOnly {
1155   TrivialMoveOnly(TrivialMoveOnly&&) = default;
1156 };
1157 
1158 // Trait class to detect whether a type is trivially move constructible.
1159 // A union's defaulted copy/move constructor is deleted if any variant member's
1160 // copy/move constructor is nontrivial.
1161 template <typename T>
1162 struct IsTriviallyMoveConstructible
1163     : std::is_move_constructible<Union<T, TrivialMoveOnly>> {};
1164 
1165 // To guarantee triviality of all special-member functions that can be trivial,
1166 // we use a chain of conditional bases for each one.
1167 // The order of inheritance of bases from child to base are logically:
1168 //
1169 // variant
1170 // VariantCopyAssignBase
1171 // VariantMoveAssignBase
1172 // VariantCopyBase
1173 // VariantMoveBase
1174 // VariantStateBaseDestructor
1175 // VariantStateBase
1176 //
1177 // Note that there is a separate branch at each base that is dependent on
1178 // whether or not that corresponding special-member-function can be trivial in
1179 // the resultant variant type.
1180 
1181 template <class... T>
1182 class VariantStateBaseDestructorNontrivial;
1183 
1184 template <class... T>
1185 class VariantMoveBaseNontrivial;
1186 
1187 template <class... T>
1188 class VariantCopyBaseNontrivial;
1189 
1190 template <class... T>
1191 class VariantMoveAssignBaseNontrivial;
1192 
1193 template <class... T>
1194 class VariantCopyAssignBaseNontrivial;
1195 
1196 // Base that is dependent on whether or not the destructor can be trivial.
1197 template <class... T>
1198 using VariantStateBaseDestructor =
1199     absl::conditional_t<std::is_destructible<Union<T...>>::value,
1200                         VariantStateBase<T...>,
1201                         VariantStateBaseDestructorNontrivial<T...>>;
1202 
1203 // Base that is dependent on whether or not the move-constructor can be
1204 // implicitly generated by the compiler (trivial or deleted).
1205 // Previously we were using `std::is_move_constructible<Union<T...>>` to check
1206 // whether all Ts have trivial move constructor, but it ran into a GCC bug:
1207 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84866
1208 // So we have to use a different approach (i.e. `HasTrivialMoveConstructor`) to
1209 // work around the bug.
1210 template <class... T>
1211 using VariantMoveBase = absl::conditional_t<
1212     absl::disjunction<
1213         absl::negation<absl::conjunction<std::is_move_constructible<T>...>>,
1214         absl::conjunction<IsTriviallyMoveConstructible<T>...>>::value,
1215     VariantStateBaseDestructor<T...>, VariantMoveBaseNontrivial<T...>>;
1216 
1217 // Base that is dependent on whether or not the copy-constructor can be trivial.
1218 template <class... T>
1219 using VariantCopyBase = absl::conditional_t<
1220     absl::disjunction<
1221         absl::negation<absl::conjunction<std::is_copy_constructible<T>...>>,
1222         std::is_copy_constructible<Union<T...>>>::value,
1223     VariantMoveBase<T...>, VariantCopyBaseNontrivial<T...>>;
1224 
1225 // Base that is dependent on whether or not the move-assign can be trivial.
1226 template <class... T>
1227 using VariantMoveAssignBase = absl::conditional_t<
1228     absl::disjunction<
1229         absl::conjunction<absl::is_move_assignable<Union<T...>>,
1230                           std::is_move_constructible<Union<T...>>,
1231                           std::is_destructible<Union<T...>>>,
1232         absl::negation<absl::conjunction<std::is_move_constructible<T>...,
1233                                          // Note: We're not qualifying this with
1234                                          // absl:: because it doesn't compile
1235                                          // under MSVC.
1236                                          is_move_assignable<T>...>>>::value,
1237     VariantCopyBase<T...>, VariantMoveAssignBaseNontrivial<T...>>;
1238 
1239 // Base that is dependent on whether or not the copy-assign can be trivial.
1240 template <class... T>
1241 using VariantCopyAssignBase = absl::conditional_t<
1242     absl::disjunction<
1243         absl::conjunction<absl::is_copy_assignable<Union<T...>>,
1244                           std::is_copy_constructible<Union<T...>>,
1245                           std::is_destructible<Union<T...>>>,
1246         absl::negation<absl::conjunction<std::is_copy_constructible<T>...,
1247                                          // Note: We're not qualifying this with
1248                                          // absl:: because it doesn't compile
1249                                          // under MSVC.
1250                                          is_copy_assignable<T>...>>>::value,
1251     VariantMoveAssignBase<T...>, VariantCopyAssignBaseNontrivial<T...>>;
1252 
1253 template <class... T>
1254 using VariantBase = VariantCopyAssignBase<T...>;
1255 
1256 template <class... T>
1257 class VariantStateBaseDestructorNontrivial : protected VariantStateBase<T...> {
1258  private:
1259   using Base = VariantStateBase<T...>;
1260 
1261  protected:
1262   using Base::Base;
1263 
1264   VariantStateBaseDestructorNontrivial() = default;
1265   VariantStateBaseDestructorNontrivial(VariantStateBaseDestructorNontrivial&&) =
1266       default;
1267   VariantStateBaseDestructorNontrivial(
1268       const VariantStateBaseDestructorNontrivial&) = default;
1269   VariantStateBaseDestructorNontrivial& operator=(
1270       VariantStateBaseDestructorNontrivial&&) = default;
1271   VariantStateBaseDestructorNontrivial& operator=(
1272       const VariantStateBaseDestructorNontrivial&) = default;
1273 
1274   struct Destroyer {
1275     template <std::size_t I>
1276     void operator()(SizeT<I> i) const {
1277       using Alternative =
1278           typename absl::variant_alternative<I, variant<T...>>::type;
1279       variant_internal::AccessUnion(self->state_, i).~Alternative();
1280     }
1281 
1282     void operator()(SizeT<absl::variant_npos> /*i*/) const {
1283       // This space intentionally left blank
1284     }
1285 
1286     VariantStateBaseDestructorNontrivial* self;
1287   };
1288 
1289   void destroy() { VisitIndices<sizeof...(T)>::Run(Destroyer{this}, index_); }
1290 
1291   ~VariantStateBaseDestructorNontrivial() { destroy(); }
1292 
1293  protected:
1294   using Base::index_;
1295   using Base::state_;
1296 };
1297 
1298 template <class... T>
1299 class VariantMoveBaseNontrivial : protected VariantStateBaseDestructor<T...> {
1300  private:
1301   using Base = VariantStateBaseDestructor<T...>;
1302 
1303  protected:
1304   using Base::Base;
1305 
1306   struct Construct {
1307     template <std::size_t I>
1308     void operator()(SizeT<I> i) const {
1309       using Alternative =
1310           typename absl::variant_alternative<I, variant<T...>>::type;
1311       ::new (static_cast<void*>(&self->state_)) Alternative(
1312           variant_internal::AccessUnion(std::move(other->state_), i));
1313     }
1314 
1315     void operator()(SizeT<absl::variant_npos> /*i*/) const {}
1316 
1317     VariantMoveBaseNontrivial* self;
1318     VariantMoveBaseNontrivial* other;
1319   };
1320 
1321   VariantMoveBaseNontrivial() = default;
1322   VariantMoveBaseNontrivial(VariantMoveBaseNontrivial&& other) noexcept(
1323       absl::conjunction<std::is_nothrow_move_constructible<T>...>::value)
1324       : Base(NoopConstructorTag()) {
1325     VisitIndices<sizeof...(T)>::Run(Construct{this, &other}, other.index_);
1326     index_ = other.index_;
1327   }
1328 
1329   VariantMoveBaseNontrivial(VariantMoveBaseNontrivial const&) = default;
1330 
1331   VariantMoveBaseNontrivial& operator=(VariantMoveBaseNontrivial&&) = default;
1332   VariantMoveBaseNontrivial& operator=(VariantMoveBaseNontrivial const&) =
1333       default;
1334 
1335  protected:
1336   using Base::index_;
1337   using Base::state_;
1338 };
1339 
1340 template <class... T>
1341 class VariantCopyBaseNontrivial : protected VariantMoveBase<T...> {
1342  private:
1343   using Base = VariantMoveBase<T...>;
1344 
1345  protected:
1346   using Base::Base;
1347 
1348   VariantCopyBaseNontrivial() = default;
1349   VariantCopyBaseNontrivial(VariantCopyBaseNontrivial&&) = default;
1350 
1351   struct Construct {
1352     template <std::size_t I>
1353     void operator()(SizeT<I> i) const {
1354       using Alternative =
1355           typename absl::variant_alternative<I, variant<T...>>::type;
1356       ::new (static_cast<void*>(&self->state_))
1357           Alternative(variant_internal::AccessUnion(other->state_, i));
1358     }
1359 
1360     void operator()(SizeT<absl::variant_npos> /*i*/) const {}
1361 
1362     VariantCopyBaseNontrivial* self;
1363     const VariantCopyBaseNontrivial* other;
1364   };
1365 
1366   VariantCopyBaseNontrivial(VariantCopyBaseNontrivial const& other)
1367       : Base(NoopConstructorTag()) {
1368     VisitIndices<sizeof...(T)>::Run(Construct{this, &other}, other.index_);
1369     index_ = other.index_;
1370   }
1371 
1372   VariantCopyBaseNontrivial& operator=(VariantCopyBaseNontrivial&&) = default;
1373   VariantCopyBaseNontrivial& operator=(VariantCopyBaseNontrivial const&) =
1374       default;
1375 
1376  protected:
1377   using Base::index_;
1378   using Base::state_;
1379 };
1380 
1381 template <class... T>
1382 class VariantMoveAssignBaseNontrivial : protected VariantCopyBase<T...> {
1383   friend struct VariantCoreAccess;
1384 
1385  private:
1386   using Base = VariantCopyBase<T...>;
1387 
1388  protected:
1389   using Base::Base;
1390 
1391   VariantMoveAssignBaseNontrivial() = default;
1392   VariantMoveAssignBaseNontrivial(VariantMoveAssignBaseNontrivial&&) = default;
1393   VariantMoveAssignBaseNontrivial(const VariantMoveAssignBaseNontrivial&) =
1394       default;
1395   VariantMoveAssignBaseNontrivial& operator=(
1396       VariantMoveAssignBaseNontrivial const&) = default;
1397 
1398   VariantMoveAssignBaseNontrivial&
1399   operator=(VariantMoveAssignBaseNontrivial&& other) noexcept(
1400       absl::conjunction<std::is_nothrow_move_constructible<T>...,
1401                         std::is_nothrow_move_assignable<T>...>::value) {
1402     VisitIndices<sizeof...(T)>::Run(
1403         VariantCoreAccess::MakeMoveAssignVisitor(this, &other), other.index_);
1404     return *this;
1405   }
1406 
1407  protected:
1408   using Base::index_;
1409   using Base::state_;
1410 };
1411 
1412 template <class... T>
1413 class VariantCopyAssignBaseNontrivial : protected VariantMoveAssignBase<T...> {
1414   friend struct VariantCoreAccess;
1415 
1416  private:
1417   using Base = VariantMoveAssignBase<T...>;
1418 
1419  protected:
1420   using Base::Base;
1421 
1422   VariantCopyAssignBaseNontrivial() = default;
1423   VariantCopyAssignBaseNontrivial(VariantCopyAssignBaseNontrivial&&) = default;
1424   VariantCopyAssignBaseNontrivial(const VariantCopyAssignBaseNontrivial&) =
1425       default;
1426   VariantCopyAssignBaseNontrivial& operator=(
1427       VariantCopyAssignBaseNontrivial&&) = default;
1428 
1429   VariantCopyAssignBaseNontrivial& operator=(
1430       const VariantCopyAssignBaseNontrivial& other) {
1431     VisitIndices<sizeof...(T)>::Run(
1432         VariantCoreAccess::MakeCopyAssignVisitor(this, other), other.index_);
1433     return *this;
1434   }
1435 
1436  protected:
1437   using Base::index_;
1438   using Base::state_;
1439 };
1440 
1441 ////////////////////////////////////////
1442 // Visitors for Comparison Operations //
1443 ////////////////////////////////////////
1444 
1445 template <class... Types>
1446 struct EqualsOp {
1447   const variant<Types...>* v;
1448   const variant<Types...>* w;
1449 
1450   constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
1451     return true;
1452   }
1453 
1454   template <std::size_t I>
1455   constexpr bool operator()(SizeT<I> /*v_i*/) const {
1456     return VariantCoreAccess::Access<I>(*v) == VariantCoreAccess::Access<I>(*w);
1457   }
1458 };
1459 
1460 template <class... Types>
1461 struct NotEqualsOp {
1462   const variant<Types...>* v;
1463   const variant<Types...>* w;
1464 
1465   constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
1466     return false;
1467   }
1468 
1469   template <std::size_t I>
1470   constexpr bool operator()(SizeT<I> /*v_i*/) const {
1471     return VariantCoreAccess::Access<I>(*v) != VariantCoreAccess::Access<I>(*w);
1472   }
1473 };
1474 
1475 template <class... Types>
1476 struct LessThanOp {
1477   const variant<Types...>* v;
1478   const variant<Types...>* w;
1479 
1480   constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
1481     return false;
1482   }
1483 
1484   template <std::size_t I>
1485   constexpr bool operator()(SizeT<I> /*v_i*/) const {
1486     return VariantCoreAccess::Access<I>(*v) < VariantCoreAccess::Access<I>(*w);
1487   }
1488 };
1489 
1490 template <class... Types>
1491 struct GreaterThanOp {
1492   const variant<Types...>* v;
1493   const variant<Types...>* w;
1494 
1495   constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
1496     return false;
1497   }
1498 
1499   template <std::size_t I>
1500   constexpr bool operator()(SizeT<I> /*v_i*/) const {
1501     return VariantCoreAccess::Access<I>(*v) > VariantCoreAccess::Access<I>(*w);
1502   }
1503 };
1504 
1505 template <class... Types>
1506 struct LessThanOrEqualsOp {
1507   const variant<Types...>* v;
1508   const variant<Types...>* w;
1509 
1510   constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
1511     return true;
1512   }
1513 
1514   template <std::size_t I>
1515   constexpr bool operator()(SizeT<I> /*v_i*/) const {
1516     return VariantCoreAccess::Access<I>(*v) <= VariantCoreAccess::Access<I>(*w);
1517   }
1518 };
1519 
1520 template <class... Types>
1521 struct GreaterThanOrEqualsOp {
1522   const variant<Types...>* v;
1523   const variant<Types...>* w;
1524 
1525   constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
1526     return true;
1527   }
1528 
1529   template <std::size_t I>
1530   constexpr bool operator()(SizeT<I> /*v_i*/) const {
1531     return VariantCoreAccess::Access<I>(*v) >= VariantCoreAccess::Access<I>(*w);
1532   }
1533 };
1534 
1535 // Precondition: v.index() == w.index();
1536 template <class... Types>
1537 struct SwapSameIndex {
1538   variant<Types...>* v;
1539   variant<Types...>* w;
1540   template <std::size_t I>
1541   void operator()(SizeT<I>) const {
1542     type_traits_internal::Swap(VariantCoreAccess::Access<I>(*v),
1543                                VariantCoreAccess::Access<I>(*w));
1544   }
1545 
1546   void operator()(SizeT<variant_npos>) const {}
1547 };
1548 
1549 // TODO(calabrese) do this from a different namespace for proper adl usage
1550 template <class... Types>
1551 struct Swap {
1552   variant<Types...>* v;
1553   variant<Types...>* w;
1554 
1555   void generic_swap() const {
1556     variant<Types...> tmp(std::move(*w));
1557     VariantCoreAccess::Destroy(*w);
1558     VariantCoreAccess::InitFrom(*w, std::move(*v));
1559     VariantCoreAccess::Destroy(*v);
1560     VariantCoreAccess::InitFrom(*v, std::move(tmp));
1561   }
1562 
1563   void operator()(SizeT<absl::variant_npos> /*w_i*/) const {
1564     if (!v->valueless_by_exception()) {
1565       generic_swap();
1566     }
1567   }
1568 
1569   template <std::size_t Wi>
1570   void operator()(SizeT<Wi> /*w_i*/) {
1571     if (v->index() == Wi) {
1572       VisitIndices<sizeof...(Types)>::Run(SwapSameIndex<Types...>{v, w}, Wi);
1573     } else {
1574       generic_swap();
1575     }
1576   }
1577 };
1578 
1579 template <typename Variant, typename = void, typename... Ts>
1580 struct VariantHashBase {
1581   VariantHashBase() = delete;
1582   VariantHashBase(const VariantHashBase&) = delete;
1583   VariantHashBase(VariantHashBase&&) = delete;
1584   VariantHashBase& operator=(const VariantHashBase&) = delete;
1585   VariantHashBase& operator=(VariantHashBase&&) = delete;
1586 };
1587 
1588 struct VariantHashVisitor {
1589   template <typename T>
1590   size_t operator()(const T& t) {
1591     return std::hash<T>{}(t);
1592   }
1593 };
1594 
1595 template <typename Variant, typename... Ts>
1596 struct VariantHashBase<Variant,
1597                        absl::enable_if_t<absl::conjunction<
1598                            type_traits_internal::IsHashable<Ts>...>::value>,
1599                        Ts...> {
1600   using argument_type = Variant;
1601   using result_type = size_t;
1602   size_t operator()(const Variant& var) const {
1603     type_traits_internal::AssertHashEnabled<Ts...>();
1604     if (var.valueless_by_exception()) {
1605       return 239799884;
1606     }
1607     size_t result = VisitIndices<variant_size<Variant>::value>::Run(
1608         PerformVisitation<VariantHashVisitor, const Variant&>{
1609             std::forward_as_tuple(var), VariantHashVisitor{}},
1610         var.index());
1611     // Combine the index and the hash result in order to distinguish
1612     // std::variant<int, int> holding the same value as different alternative.
1613     return result ^ var.index();
1614   }
1615 };
1616 
1617 }  // namespace variant_internal
1618 ABSL_NAMESPACE_END
1619 }  // namespace absl
1620 
1621 #endif  // !defined(ABSL_USES_STD_VARIANT)
1622 #endif  // ABSL_TYPES_INTERNAL_VARIANT_H_