variant.h
Go to the documentation of this file.
00001 // Copyright 2018 The Abseil Authors.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //      https://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 // Unless required by applicable law or agreed to in writing, software
00010 // distributed under the License is distributed on an "AS IS" BASIS,
00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 // See the License for the specific language governing permissions and
00013 // limitations under the License.
00014 //
00015 // Implementation details of absl/types/variant.h, pulled into a
00016 // separate file to avoid cluttering the top of the API header with
00017 // implementation details.
00018 
00019 #ifndef ABSL_TYPES_variant_internal_H_
00020 #define ABSL_TYPES_variant_internal_H_
00021 
00022 #include <cassert>
00023 #include <cstddef>
00024 #include <cstdlib>
00025 #include <memory>
00026 #include <stdexcept>
00027 #include <tuple>
00028 #include <type_traits>
00029 
00030 #include "absl/base/config.h"
00031 #include "absl/base/internal/identity.h"
00032 #include "absl/base/internal/inline_variable.h"
00033 #include "absl/base/internal/invoke.h"
00034 #include "absl/base/macros.h"
00035 #include "absl/base/optimization.h"
00036 #include "absl/meta/type_traits.h"
00037 #include "absl/types/bad_variant_access.h"
00038 #include "absl/utility/utility.h"
00039 
00040 #if !defined(ABSL_HAVE_STD_VARIANT)
00041 
00042 namespace absl {
00043 
00044 template <class... Types>
00045 class variant;
00046 
00047 ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, -1);
00048 
00049 template <class T>
00050 struct variant_size;
00051 
00052 template <std::size_t I, class T>
00053 struct variant_alternative;
00054 
00055 namespace variant_internal {
00056 
00057 // NOTE: See specializations below for details.
00058 template <std::size_t I, class T>
00059 struct VariantAlternativeSfinae {};
00060 
00061 // Requires: I < variant_size_v<T>.
00062 //
00063 // Value: The Ith type of Types...
00064 template <std::size_t I, class T0, class... Tn>
00065 struct VariantAlternativeSfinae<I, variant<T0, Tn...>>
00066     : VariantAlternativeSfinae<I - 1, variant<Tn...>> {};
00067 
00068 // Value: T0
00069 template <class T0, class... Ts>
00070 struct VariantAlternativeSfinae<0, variant<T0, Ts...>> {
00071   using type = T0;
00072 };
00073 
00074 template <std::size_t I, class T>
00075 using VariantAlternativeSfinaeT = typename VariantAlternativeSfinae<I, T>::type;
00076 
00077 // NOTE: Requires T to be a reference type.
00078 template <class T, class U>
00079 struct GiveQualsTo;
00080 
00081 template <class T, class U>
00082 struct GiveQualsTo<T&, U> {
00083   using type = U&;
00084 };
00085 
00086 template <class T, class U>
00087 struct GiveQualsTo<T&&, U> {
00088   using type = U&&;
00089 };
00090 
00091 template <class T, class U>
00092 struct GiveQualsTo<const T&, U> {
00093   using type = const U&;
00094 };
00095 
00096 template <class T, class U>
00097 struct GiveQualsTo<const T&&, U> {
00098   using type = const U&&;
00099 };
00100 
00101 template <class T, class U>
00102 struct GiveQualsTo<volatile T&, U> {
00103   using type = volatile U&;
00104 };
00105 
00106 template <class T, class U>
00107 struct GiveQualsTo<volatile T&&, U> {
00108   using type = volatile U&&;
00109 };
00110 
00111 template <class T, class U>
00112 struct GiveQualsTo<volatile const T&, U> {
00113   using type = volatile const U&;
00114 };
00115 
00116 template <class T, class U>
00117 struct GiveQualsTo<volatile const T&&, U> {
00118   using type = volatile const U&&;
00119 };
00120 
00121 template <class T, class U>
00122 using GiveQualsToT = typename GiveQualsTo<T, U>::type;
00123 
00124 // Convenience alias, since size_t integral_constant is used a lot in this file.
00125 template <std::size_t I>
00126 using SizeT = std::integral_constant<std::size_t, I>;
00127 
00128 using NPos = SizeT<variant_npos>;
00129 
00130 template <class Variant, class T, class = void>
00131 struct IndexOfConstructedType {};
00132 
00133 template <std::size_t I, class Variant>
00134 struct VariantAccessResultImpl;
00135 
00136 template <std::size_t I, template <class...> class Variantemplate, class... T>
00137 struct VariantAccessResultImpl<I, Variantemplate<T...>&> {
00138   using type = typename absl::variant_alternative<I, variant<T...>>::type&;
00139 };
00140 
00141 template <std::size_t I, template <class...> class Variantemplate, class... T>
00142 struct VariantAccessResultImpl<I, const Variantemplate<T...>&> {
00143   using type =
00144       const typename absl::variant_alternative<I, variant<T...>>::type&;
00145 };
00146 
00147 template <std::size_t I, template <class...> class Variantemplate, class... T>
00148 struct VariantAccessResultImpl<I, Variantemplate<T...>&&> {
00149   using type = typename absl::variant_alternative<I, variant<T...>>::type&&;
00150 };
00151 
00152 template <std::size_t I, template <class...> class Variantemplate, class... T>
00153 struct VariantAccessResultImpl<I, const Variantemplate<T...>&&> {
00154   using type =
00155       const typename absl::variant_alternative<I, variant<T...>>::type&&;
00156 };
00157 
00158 template <std::size_t I, class Variant>
00159 using VariantAccessResult =
00160     typename VariantAccessResultImpl<I, Variant&&>::type;
00161 
00162 // NOTE: This is used instead of std::array to reduce instantiation overhead.
00163 template <class T, std::size_t Size>
00164 struct SimpleArray {
00165   static_assert(Size != 0, "");
00166   T value[Size];
00167 };
00168 
00169 template <class T>
00170 struct AccessedType {
00171   using type = T;
00172 };
00173 
00174 template <class T>
00175 using AccessedTypeT = typename AccessedType<T>::type;
00176 
00177 template <class T, std::size_t Size>
00178 struct AccessedType<SimpleArray<T, Size>> {
00179   using type = AccessedTypeT<T>;
00180 };
00181 
00182 template <class T>
00183 constexpr T AccessSimpleArray(const T& value) {
00184   return value;
00185 }
00186 
00187 template <class T, std::size_t Size, class... SizeT>
00188 constexpr AccessedTypeT<T> AccessSimpleArray(const SimpleArray<T, Size>& table,
00189                                              std::size_t head_index,
00190                                              SizeT... tail_indices) {
00191   return AccessSimpleArray(table.value[head_index], tail_indices...);
00192 }
00193 
00194 // Note: Intentionally is an alias.
00195 template <class T>
00196 using AlwaysZero = SizeT<0>;
00197 
00198 template <class Op, class... Vs>
00199 struct VisitIndicesResultImpl {
00200   using type = absl::result_of_t<Op(AlwaysZero<Vs>...)>;
00201 };
00202 
00203 template <class Op, class... Vs>
00204 using VisitIndicesResultT = typename VisitIndicesResultImpl<Op, Vs...>::type;
00205 
00206 template <class ReturnType, class FunctionObject, class EndIndices,
00207           std::size_t... BoundIndices>
00208 struct MakeVisitationMatrix;
00209 
00210 template <class ReturnType, class FunctionObject, std::size_t... Indices>
00211 constexpr ReturnType call_with_indices(FunctionObject&& function) {
00212   static_assert(
00213       std::is_same<ReturnType, decltype(std::declval<FunctionObject>()(
00214                                    SizeT<Indices>()...))>::value,
00215       "Not all visitation overloads have the same return type.");
00216   return absl::forward<FunctionObject>(function)(SizeT<Indices>()...);
00217 }
00218 
00219 template <class ReturnType, class FunctionObject, std::size_t... BoundIndices>
00220 struct MakeVisitationMatrix<ReturnType, FunctionObject, index_sequence<>,
00221                             BoundIndices...> {
00222   using ResultType = ReturnType (*)(FunctionObject&&);
00223   static constexpr ResultType Run() {
00224     return &call_with_indices<ReturnType, FunctionObject,
00225                               (BoundIndices - 1)...>;
00226   }
00227 };
00228 
00229 template <class ReturnType, class FunctionObject, class EndIndices,
00230           class CurrIndices, std::size_t... BoundIndices>
00231 struct MakeVisitationMatrixImpl;
00232 
00233 template <class ReturnType, class FunctionObject, std::size_t... EndIndices,
00234           std::size_t... CurrIndices, std::size_t... BoundIndices>
00235 struct MakeVisitationMatrixImpl<
00236     ReturnType, FunctionObject, index_sequence<EndIndices...>,
00237     index_sequence<CurrIndices...>, BoundIndices...> {
00238   using ResultType = SimpleArray<
00239       typename MakeVisitationMatrix<ReturnType, FunctionObject,
00240                                     index_sequence<EndIndices...>>::ResultType,
00241       sizeof...(CurrIndices)>;
00242 
00243   static constexpr ResultType Run() {
00244     return {{MakeVisitationMatrix<ReturnType, FunctionObject,
00245                                   index_sequence<EndIndices...>,
00246                                   BoundIndices..., CurrIndices>::Run()...}};
00247   }
00248 };
00249 
00250 template <class ReturnType, class FunctionObject, std::size_t HeadEndIndex,
00251           std::size_t... TailEndIndices, std::size_t... BoundIndices>
00252 struct MakeVisitationMatrix<ReturnType, FunctionObject,
00253                             index_sequence<HeadEndIndex, TailEndIndices...>,
00254                             BoundIndices...>
00255     : MakeVisitationMatrixImpl<
00256           ReturnType, FunctionObject, index_sequence<TailEndIndices...>,
00257           absl::make_index_sequence<HeadEndIndex>, BoundIndices...> {};
00258 
00259 struct UnreachableSwitchCase {
00260   template <class Op>
00261   [[noreturn]] static VisitIndicesResultT<Op, std::size_t> Run(
00262       Op&& /*ignored*/) {
00263 #if ABSL_HAVE_BUILTIN(__builtin_unreachable) || \
00264     (defined(__GNUC__) && !defined(__clang__))
00265     __builtin_unreachable();
00266 #elif defined(_MSC_VER)
00267     __assume(false);
00268 #else
00269     // Try to use assert of false being identified as an unreachable intrinsic.
00270     // NOTE: We use assert directly to increase chances of exploiting an assume
00271     //       intrinsic.
00272     assert(false);  // NOLINT
00273 
00274     // Hack to silence potential no return warning -- cause an infinite loop.
00275     return Run(absl::forward<Op>(op));
00276 #endif  // Checks for __builtin_unreachable
00277   }
00278 };
00279 
00280 template <class Op, std::size_t I>
00281 struct ReachableSwitchCase {
00282   static VisitIndicesResultT<Op, std::size_t> Run(Op&& op) {
00283     return absl::base_internal::Invoke(absl::forward<Op>(op), SizeT<I>());
00284   }
00285 };
00286 
00287 // The number 33 is just a guess at a reasonable maximum to our switch. It is
00288 // not based on any analysis. The reason it is a power of 2 plus 1 instead of a
00289 // power of 2 is because the number was picked to correspond to a power of 2
00290 // amount of "normal" alternatives, plus one for the possibility of the user
00291 // providing "monostate" in addition to the more natural alternatives.
00292 ABSL_INTERNAL_INLINE_CONSTEXPR(std::size_t, MaxUnrolledVisitCases, 33);
00293 
00294 // Note: The default-definition is for unreachable cases.
00295 template <bool IsReachable>
00296 struct PickCaseImpl {
00297   template <class Op, std::size_t I>
00298   using Apply = UnreachableSwitchCase;
00299 };
00300 
00301 template <>
00302 struct PickCaseImpl</*IsReachable =*/true> {
00303   template <class Op, std::size_t I>
00304   using Apply = ReachableSwitchCase<Op, I>;
00305 };
00306 
00307 // Note: This form of dance with template aliases is to make sure that we
00308 //       instantiate a number of templates proportional to the number of variant
00309 //       alternatives rather than a number of templates proportional to our
00310 //       maximum unrolled amount of visitation cases (aliases are effectively
00311 //       "free" whereas other template instantiations are costly).
00312 template <class Op, std::size_t I, std::size_t EndIndex>
00313 using PickCase = typename PickCaseImpl<(I < EndIndex)>::template Apply<Op, I>;
00314 
00315 template <class ReturnType>
00316 [[noreturn]] ReturnType TypedThrowBadVariantAccess() {
00317   absl::variant_internal::ThrowBadVariantAccess();
00318 }
00319 
00320 // Given N variant sizes, determine the number of cases there would need to be
00321 // in a single switch-statement that would cover every possibility in the
00322 // corresponding N-ary visit operation.
00323 template <std::size_t... NumAlternatives>
00324 struct NumCasesOfSwitch;
00325 
00326 template <std::size_t HeadNumAlternatives, std::size_t... TailNumAlternatives>
00327 struct NumCasesOfSwitch<HeadNumAlternatives, TailNumAlternatives...> {
00328   static constexpr std::size_t value =
00329       (HeadNumAlternatives + 1) *
00330       NumCasesOfSwitch<TailNumAlternatives...>::value;
00331 };
00332 
00333 template <>
00334 struct NumCasesOfSwitch<> {
00335   static constexpr std::size_t value = 1;
00336 };
00337 
00338 // A switch statement optimizes better than the table of function pointers.
00339 template <std::size_t EndIndex>
00340 struct VisitIndicesSwitch {
00341   static_assert(EndIndex <= MaxUnrolledVisitCases,
00342                 "Maximum unrolled switch size exceeded.");
00343 
00344   template <class Op>
00345   static VisitIndicesResultT<Op, std::size_t> Run(Op&& op, std::size_t i) {
00346     switch (i) {
00347       case 0:
00348         return PickCase<Op, 0, EndIndex>::Run(absl::forward<Op>(op));
00349       case 1:
00350         return PickCase<Op, 1, EndIndex>::Run(absl::forward<Op>(op));
00351       case 2:
00352         return PickCase<Op, 2, EndIndex>::Run(absl::forward<Op>(op));
00353       case 3:
00354         return PickCase<Op, 3, EndIndex>::Run(absl::forward<Op>(op));
00355       case 4:
00356         return PickCase<Op, 4, EndIndex>::Run(absl::forward<Op>(op));
00357       case 5:
00358         return PickCase<Op, 5, EndIndex>::Run(absl::forward<Op>(op));
00359       case 6:
00360         return PickCase<Op, 6, EndIndex>::Run(absl::forward<Op>(op));
00361       case 7:
00362         return PickCase<Op, 7, EndIndex>::Run(absl::forward<Op>(op));
00363       case 8:
00364         return PickCase<Op, 8, EndIndex>::Run(absl::forward<Op>(op));
00365       case 9:
00366         return PickCase<Op, 9, EndIndex>::Run(absl::forward<Op>(op));
00367       case 10:
00368         return PickCase<Op, 10, EndIndex>::Run(absl::forward<Op>(op));
00369       case 11:
00370         return PickCase<Op, 11, EndIndex>::Run(absl::forward<Op>(op));
00371       case 12:
00372         return PickCase<Op, 12, EndIndex>::Run(absl::forward<Op>(op));
00373       case 13:
00374         return PickCase<Op, 13, EndIndex>::Run(absl::forward<Op>(op));
00375       case 14:
00376         return PickCase<Op, 14, EndIndex>::Run(absl::forward<Op>(op));
00377       case 15:
00378         return PickCase<Op, 15, EndIndex>::Run(absl::forward<Op>(op));
00379       case 16:
00380         return PickCase<Op, 16, EndIndex>::Run(absl::forward<Op>(op));
00381       case 17:
00382         return PickCase<Op, 17, EndIndex>::Run(absl::forward<Op>(op));
00383       case 18:
00384         return PickCase<Op, 18, EndIndex>::Run(absl::forward<Op>(op));
00385       case 19:
00386         return PickCase<Op, 19, EndIndex>::Run(absl::forward<Op>(op));
00387       case 20:
00388         return PickCase<Op, 20, EndIndex>::Run(absl::forward<Op>(op));
00389       case 21:
00390         return PickCase<Op, 21, EndIndex>::Run(absl::forward<Op>(op));
00391       case 22:
00392         return PickCase<Op, 22, EndIndex>::Run(absl::forward<Op>(op));
00393       case 23:
00394         return PickCase<Op, 23, EndIndex>::Run(absl::forward<Op>(op));
00395       case 24:
00396         return PickCase<Op, 24, EndIndex>::Run(absl::forward<Op>(op));
00397       case 25:
00398         return PickCase<Op, 25, EndIndex>::Run(absl::forward<Op>(op));
00399       case 26:
00400         return PickCase<Op, 26, EndIndex>::Run(absl::forward<Op>(op));
00401       case 27:
00402         return PickCase<Op, 27, EndIndex>::Run(absl::forward<Op>(op));
00403       case 28:
00404         return PickCase<Op, 28, EndIndex>::Run(absl::forward<Op>(op));
00405       case 29:
00406         return PickCase<Op, 29, EndIndex>::Run(absl::forward<Op>(op));
00407       case 30:
00408         return PickCase<Op, 30, EndIndex>::Run(absl::forward<Op>(op));
00409       case 31:
00410         return PickCase<Op, 31, EndIndex>::Run(absl::forward<Op>(op));
00411       case 32:
00412         return PickCase<Op, 32, EndIndex>::Run(absl::forward<Op>(op));
00413       default:
00414         ABSL_ASSERT(i == variant_npos);
00415         return absl::base_internal::Invoke(absl::forward<Op>(op), NPos());
00416     }
00417   }
00418 };
00419 
00420 template <std::size_t... EndIndices>
00421 struct VisitIndicesFallback {
00422   template <class Op, class... SizeT>
00423   static VisitIndicesResultT<Op, SizeT...> Run(Op&& op, SizeT... indices) {
00424     return AccessSimpleArray(
00425         MakeVisitationMatrix<VisitIndicesResultT<Op, SizeT...>, Op,
00426                              index_sequence<(EndIndices + 1)...>>::Run(),
00427         (indices + 1)...)(absl::forward<Op>(op));
00428   }
00429 };
00430 
00431 // Take an N-dimensional series of indices and convert them into a single index
00432 // without loss of information. The purpose of this is to be able to convert an
00433 // N-ary visit operation into a single switch statement.
00434 template <std::size_t...>
00435 struct FlattenIndices;
00436 
00437 template <std::size_t HeadSize, std::size_t... TailSize>
00438 struct FlattenIndices<HeadSize, TailSize...> {
00439   template<class... SizeType>
00440   static constexpr std::size_t Run(std::size_t head, SizeType... tail) {
00441     return head + HeadSize * FlattenIndices<TailSize...>::Run(tail...);
00442   }
00443 };
00444 
00445 template <>
00446 struct FlattenIndices<> {
00447   static constexpr std::size_t Run() { return 0; }
00448 };
00449 
00450 // Take a single "flattened" index (flattened by FlattenIndices) and determine
00451 // the value of the index of one of the logically represented dimensions.
00452 template <std::size_t I, std::size_t IndexToGet, std::size_t HeadSize,
00453           std::size_t... TailSize>
00454 struct UnflattenIndex {
00455   static constexpr std::size_t value =
00456       UnflattenIndex<I / HeadSize, IndexToGet - 1, TailSize...>::value;
00457 };
00458 
00459 template <std::size_t I, std::size_t HeadSize, std::size_t... TailSize>
00460 struct UnflattenIndex<I, 0, HeadSize, TailSize...> {
00461   static constexpr std::size_t value = (I % HeadSize);
00462 };
00463 
00464 // The backend for converting an N-ary visit operation into a unary visit.
00465 template <class IndexSequence, std::size_t... EndIndices>
00466 struct VisitIndicesVariadicImpl;
00467 
00468 template <std::size_t... N, std::size_t... EndIndices>
00469 struct VisitIndicesVariadicImpl<absl::index_sequence<N...>, EndIndices...> {
00470   // A type that can take an N-ary function object and converts it to a unary
00471   // function object that takes a single, flattened index, and "unflattens" it
00472   // into its individual dimensions when forwarding to the wrapped object.
00473   template <class Op>
00474   struct FlattenedOp {
00475     template <std::size_t I>
00476     VisitIndicesResultT<Op, decltype(EndIndices)...> operator()(
00477         SizeT<I> /*index*/) && {
00478       return base_internal::Invoke(
00479           absl::forward<Op>(op),
00480           SizeT<UnflattenIndex<I, N, (EndIndices + 1)...>::value -
00481                 std::size_t{1}>()...);
00482     }
00483 
00484     Op&& op;
00485   };
00486 
00487   template <class Op, class... SizeType>
00488   static VisitIndicesResultT<Op, decltype(EndIndices)...> Run(
00489       Op&& op, SizeType... i) {
00490     return VisitIndicesSwitch<NumCasesOfSwitch<EndIndices...>::value>::Run(
00491         FlattenedOp<Op>{absl::forward<Op>(op)},
00492         FlattenIndices<(EndIndices + std::size_t{1})...>::Run(
00493             (i + std::size_t{1})...));
00494   }
00495 };
00496 
00497 template <std::size_t... EndIndices>
00498 struct VisitIndicesVariadic
00499     : VisitIndicesVariadicImpl<absl::make_index_sequence<sizeof...(EndIndices)>,
00500                                EndIndices...> {};
00501 
00502 // This implementation will flatten N-ary visit operations into a single switch
00503 // statement when the number of cases would be less than our maximum specified
00504 // switch-statement size.
00505 // TODO(calabrese)
00506 //   Based on benchmarks, determine whether the function table approach actually
00507 //   does optimize better than a chain of switch statements and possibly update
00508 //   the implementation accordingly. Also consider increasing the maximum switch
00509 //   size.
00510 template <std::size_t... EndIndices>
00511 struct VisitIndices
00512     : absl::conditional_t<(NumCasesOfSwitch<EndIndices...>::value <=
00513                            MaxUnrolledVisitCases),
00514                           VisitIndicesVariadic<EndIndices...>,
00515                           VisitIndicesFallback<EndIndices...>> {};
00516 
00517 template <std::size_t EndIndex>
00518 struct VisitIndices<EndIndex>
00519     : absl::conditional_t<(EndIndex <= MaxUnrolledVisitCases),
00520                           VisitIndicesSwitch<EndIndex>,
00521                           VisitIndicesFallback<EndIndex>> {};
00522 
00523 // Suppress bogus warning on MSVC: MSVC complains that the `reinterpret_cast`
00524 // below is returning the address of a temporary or local object.
00525 #ifdef _MSC_VER
00526 #pragma warning(push)
00527 #pragma warning(disable : 4172)
00528 #endif  // _MSC_VER
00529 
00530 // TODO(calabrese) std::launder
00531 // TODO(calabrese) constexpr
00532 // NOTE: DO NOT REMOVE the `inline` keyword as it is necessary to work around a
00533 // MSVC bug. See https://github.com/abseil/abseil-cpp/issues/129 for details.
00534 template <class Self, std::size_t I>
00535 inline VariantAccessResult<I, Self> AccessUnion(Self&& self, SizeT<I> /*i*/) {
00536   return reinterpret_cast<VariantAccessResult<I, Self>>(self);
00537 }
00538 
00539 #ifdef _MSC_VER
00540 #pragma warning(pop)
00541 #endif  // _MSC_VER
00542 
00543 template <class T>
00544 void DeducedDestroy(T& self) {  // NOLINT
00545   self.~T();
00546 }
00547 
00548 // NOTE: This type exists as a single entity for variant and its bases to
00549 // befriend. It contains helper functionality that manipulates the state of the
00550 // variant, such as the implementation of things like assignment and emplace
00551 // operations.
00552 struct VariantCoreAccess {
00553   template <class VariantType>
00554   static typename VariantType::Variant& Derived(VariantType& self) {  // NOLINT
00555     return static_cast<typename VariantType::Variant&>(self);
00556   }
00557 
00558   template <class VariantType>
00559   static const typename VariantType::Variant& Derived(
00560       const VariantType& self) {  // NOLINT
00561     return static_cast<const typename VariantType::Variant&>(self);
00562   }
00563 
00564   template <class VariantType>
00565   static void Destroy(VariantType& self) {  // NOLINT
00566     Derived(self).destroy();
00567     self.index_ = absl::variant_npos;
00568   }
00569 
00570   template <class Variant>
00571   static void SetIndex(Variant& self, std::size_t i) {  // NOLINT
00572     self.index_ = i;
00573   }
00574 
00575   template <class Variant>
00576   static void InitFrom(Variant& self, Variant&& other) {  // NOLINT
00577     VisitIndices<absl::variant_size<Variant>::value>::Run(
00578         InitFromVisitor<Variant, Variant&&>{&self,
00579                                             std::forward<Variant>(other)},
00580         other.index());
00581     self.index_ = other.index();
00582   }
00583 
00584   // Access a variant alternative, assuming the index is correct.
00585   template <std::size_t I, class Variant>
00586   static VariantAccessResult<I, Variant> Access(Variant&& self) {
00587     // This cast instead of invocation of AccessUnion with an rvalue is a
00588     // workaround for msvc. Without this there is a runtime failure when dealing
00589     // with rvalues.
00590     // TODO(calabrese) Reduce test case and find a simpler workaround.
00591     return static_cast<VariantAccessResult<I, Variant>>(
00592         variant_internal::AccessUnion(self.state_, SizeT<I>()));
00593   }
00594 
00595   // Access a variant alternative, throwing if the index is incorrect.
00596   template <std::size_t I, class Variant>
00597   static VariantAccessResult<I, Variant> CheckedAccess(Variant&& self) {
00598     if (ABSL_PREDICT_FALSE(self.index_ != I)) {
00599       TypedThrowBadVariantAccess<VariantAccessResult<I, Variant>>();
00600     }
00601 
00602     return Access<I>(absl::forward<Variant>(self));
00603   }
00604 
00605   // The implementation of the move-assignment operation for a variant.
00606   template <class VType>
00607   struct MoveAssignVisitor {
00608     using DerivedType = typename VType::Variant;
00609     template <std::size_t NewIndex>
00610     void operator()(SizeT<NewIndex> /*new_i*/) const {
00611       if (left->index_ == NewIndex) {
00612         Access<NewIndex>(*left) = std::move(Access<NewIndex>(*right));
00613       } else {
00614         Derived(*left).template emplace<NewIndex>(
00615             std::move(Access<NewIndex>(*right)));
00616       }
00617     }
00618 
00619     void operator()(SizeT<absl::variant_npos> /*new_i*/) const {
00620       Destroy(*left);
00621     }
00622 
00623     VType* left;
00624     VType* right;
00625   };
00626 
00627   template <class VType>
00628   static MoveAssignVisitor<VType> MakeMoveAssignVisitor(VType* left,
00629                                                         VType* other) {
00630     return {left, other};
00631   }
00632 
00633   // The implementation of the assignment operation for a variant.
00634   template <class VType>
00635   struct CopyAssignVisitor {
00636     using DerivedType = typename VType::Variant;
00637     template <std::size_t NewIndex>
00638     void operator()(SizeT<NewIndex> /*new_i*/) const {
00639       using New =
00640           typename absl::variant_alternative<NewIndex, DerivedType>::type;
00641 
00642       if (left->index_ == NewIndex) {
00643         Access<NewIndex>(*left) = Access<NewIndex>(*right);
00644       } else if (std::is_nothrow_copy_constructible<New>::value ||
00645                  !std::is_nothrow_move_constructible<New>::value) {
00646         Derived(*left).template emplace<NewIndex>(Access<NewIndex>(*right));
00647       } else {
00648         Derived(*left) = DerivedType(Derived(*right));
00649       }
00650     }
00651 
00652     void operator()(SizeT<absl::variant_npos> /*new_i*/) const {
00653       Destroy(*left);
00654     }
00655 
00656     VType* left;
00657     const VType* right;
00658   };
00659 
00660   template <class VType>
00661   static CopyAssignVisitor<VType> MakeCopyAssignVisitor(VType* left,
00662                                                         const VType& other) {
00663     return {left, &other};
00664   }
00665 
00666   // The implementation of conversion-assignment operations for variant.
00667   template <class Left, class QualifiedNew>
00668   struct ConversionAssignVisitor {
00669     using NewIndex =
00670         variant_internal::IndexOfConstructedType<Left, QualifiedNew>;
00671 
00672     void operator()(SizeT<NewIndex::value> /*old_i*/
00673                     ) const {
00674       Access<NewIndex::value>(*left) = absl::forward<QualifiedNew>(other);
00675     }
00676 
00677     template <std::size_t OldIndex>
00678     void operator()(SizeT<OldIndex> /*old_i*/
00679                     ) const {
00680       using New =
00681           typename absl::variant_alternative<NewIndex::value, Left>::type;
00682       if (std::is_nothrow_constructible<New, QualifiedNew>::value ||
00683           !std::is_nothrow_move_constructible<New>::value) {
00684         left->template emplace<NewIndex::value>(
00685             absl::forward<QualifiedNew>(other));
00686       } else {
00687         // the standard says "equivalent to
00688         // operator=(variant(std::forward<T>(t)))", but we use `emplace` here
00689         // because the variant's move assignment operator could be deleted.
00690         left->template emplace<NewIndex::value>(
00691             New(absl::forward<QualifiedNew>(other)));
00692       }
00693     }
00694 
00695     Left* left;
00696     QualifiedNew&& other;
00697   };
00698 
00699   template <class Left, class QualifiedNew>
00700   static ConversionAssignVisitor<Left, QualifiedNew>
00701   MakeConversionAssignVisitor(Left* left, QualifiedNew&& qual) {
00702     return {left, absl::forward<QualifiedNew>(qual)};
00703   }
00704 
00705   // Backend for operations for `emplace()` which destructs `*self` then
00706   // construct a new alternative with `Args...`.
00707   template <std::size_t NewIndex, class Self, class... Args>
00708   static typename absl::variant_alternative<NewIndex, Self>::type& Replace(
00709       Self* self, Args&&... args) {
00710     Destroy(*self);
00711     using New = typename absl::variant_alternative<NewIndex, Self>::type;
00712     New* const result = ::new (static_cast<void*>(&self->state_))
00713         New(absl::forward<Args>(args)...);
00714     self->index_ = NewIndex;
00715     return *result;
00716   }
00717 
00718   template <class LeftVariant, class QualifiedRightVariant>
00719   struct InitFromVisitor {
00720     template <std::size_t NewIndex>
00721     void operator()(SizeT<NewIndex> /*new_i*/) const {
00722       using Alternative =
00723           typename variant_alternative<NewIndex, LeftVariant>::type;
00724       ::new (static_cast<void*>(&left->state_)) Alternative(
00725           Access<NewIndex>(std::forward<QualifiedRightVariant>(right)));
00726     }
00727 
00728     void operator()(SizeT<absl::variant_npos> /*new_i*/) const {
00729       // This space intentionally left blank.
00730     }
00731     LeftVariant* left;
00732     QualifiedRightVariant&& right;
00733   };
00734 };
00735 
00736 template <class Expected, class... T>
00737 struct IndexOfImpl;
00738 
00739 template <class Expected>
00740 struct IndexOfImpl<Expected> {
00741   using IndexFromEnd = SizeT<0>;
00742   using MatchedIndexFromEnd = IndexFromEnd;
00743   using MultipleMatches = std::false_type;
00744 };
00745 
00746 template <class Expected, class Head, class... Tail>
00747 struct IndexOfImpl<Expected, Head, Tail...> : IndexOfImpl<Expected, Tail...> {
00748   using IndexFromEnd =
00749       SizeT<IndexOfImpl<Expected, Tail...>::IndexFromEnd::value + 1>;
00750 };
00751 
00752 template <class Expected, class... Tail>
00753 struct IndexOfImpl<Expected, Expected, Tail...>
00754     : IndexOfImpl<Expected, Tail...> {
00755   using IndexFromEnd =
00756       SizeT<IndexOfImpl<Expected, Tail...>::IndexFromEnd::value + 1>;
00757   using MatchedIndexFromEnd = IndexFromEnd;
00758   using MultipleMatches = std::integral_constant<
00759       bool, IndexOfImpl<Expected, Tail...>::MatchedIndexFromEnd::value != 0>;
00760 };
00761 
00762 template <class Expected, class... Types>
00763 struct IndexOfMeta {
00764   using Results = IndexOfImpl<Expected, Types...>;
00765   static_assert(!Results::MultipleMatches::value,
00766                 "Attempted to access a variant by specifying a type that "
00767                 "matches more than one alternative.");
00768   static_assert(Results::MatchedIndexFromEnd::value != 0,
00769                 "Attempted to access a variant by specifying a type that does "
00770                 "not match any alternative.");
00771   using type = SizeT<sizeof...(Types) - Results::MatchedIndexFromEnd::value>;
00772 };
00773 
00774 template <class Expected, class... Types>
00775 using IndexOf = typename IndexOfMeta<Expected, Types...>::type;
00776 
00777 template <class Variant, class T, std::size_t CurrIndex>
00778 struct UnambiguousIndexOfImpl;
00779 
00780 // Terminating case encountered once we've checked all of the alternatives
00781 template <class T, std::size_t CurrIndex>
00782 struct UnambiguousIndexOfImpl<variant<>, T, CurrIndex> : SizeT<CurrIndex> {};
00783 
00784 // Case where T is not Head
00785 template <class Head, class... Tail, class T, std::size_t CurrIndex>
00786 struct UnambiguousIndexOfImpl<variant<Head, Tail...>, T, CurrIndex>
00787     : UnambiguousIndexOfImpl<variant<Tail...>, T, CurrIndex + 1>::type {};
00788 
00789 // Case where T is Head
00790 template <class Head, class... Tail, std::size_t CurrIndex>
00791 struct UnambiguousIndexOfImpl<variant<Head, Tail...>, Head, CurrIndex>
00792     : SizeT<UnambiguousIndexOfImpl<variant<Tail...>, Head, 0>::value ==
00793                     sizeof...(Tail)
00794                 ? CurrIndex
00795                 : CurrIndex + sizeof...(Tail) + 1> {};
00796 
00797 template <class Variant, class T>
00798 struct UnambiguousIndexOf;
00799 
00800 struct NoMatch {
00801   struct type {};
00802 };
00803 
00804 template <class... Alts, class T>
00805 struct UnambiguousIndexOf<variant<Alts...>, T>
00806     : std::conditional<UnambiguousIndexOfImpl<variant<Alts...>, T, 0>::value !=
00807                            sizeof...(Alts),
00808                        UnambiguousIndexOfImpl<variant<Alts...>, T, 0>,
00809                        NoMatch>::type::type {};
00810 
00811 template <class T, std::size_t /*Dummy*/>
00812 using UnambiguousTypeOfImpl = T;
00813 
00814 template <class Variant, class T>
00815 using UnambiguousTypeOfT =
00816     UnambiguousTypeOfImpl<T, UnambiguousIndexOf<Variant, T>::value>;
00817 
00818 template <class H, class... T>
00819 class VariantStateBase;
00820 
00821 // This is an implementation of the "imaginary function" that is described in
00822 // [variant.ctor]
00823 // It is used in order to determine which alternative to construct during
00824 // initialization from some type T.
00825 template <class Variant, std::size_t I = 0>
00826 struct ImaginaryFun;
00827 
00828 template <std::size_t I>
00829 struct ImaginaryFun<variant<>, I> {
00830   static void Run() = delete;
00831 };
00832 
00833 template <class H, class... T, std::size_t I>
00834 struct ImaginaryFun<variant<H, T...>, I> : ImaginaryFun<variant<T...>, I + 1> {
00835   using ImaginaryFun<variant<T...>, I + 1>::Run;
00836 
00837   // NOTE: const& and && are used instead of by-value due to lack of guaranteed
00838   // move elision of C++17. This may have other minor differences, but tests
00839   // pass.
00840   static SizeT<I> Run(const H&);
00841   static SizeT<I> Run(H&&);
00842 };
00843 
00844 // The following metafunctions are used in constructor and assignment
00845 // constraints.
00846 template <class Self, class T>
00847 struct IsNeitherSelfNorInPlace : std::true_type {};
00848 
00849 template <class Self>
00850 struct IsNeitherSelfNorInPlace<Self, Self> : std::false_type {};
00851 
00852 template <class Self, class T>
00853 struct IsNeitherSelfNorInPlace<Self, in_place_type_t<T>> : std::false_type {};
00854 
00855 template <class Self, std::size_t I>
00856 struct IsNeitherSelfNorInPlace<Self, in_place_index_t<I>> : std::false_type {};
00857 
00858 template <class Variant, class T, class = void>
00859 struct ConversionIsPossibleImpl : std::false_type {};
00860 
00861 template <class Variant, class T>
00862 struct ConversionIsPossibleImpl<
00863     Variant, T, void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>()))>>
00864     : std::true_type {};
00865 
00866 template <class Variant, class T>
00867 struct ConversionIsPossible : ConversionIsPossibleImpl<Variant, T>::type {};
00868 
00869 template <class Variant, class T>
00870 struct IndexOfConstructedType<
00871     Variant, T, void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>()))>>
00872     : decltype(ImaginaryFun<Variant>::Run(std::declval<T>())) {};
00873 
00874 template <std::size_t... Is>
00875 struct ContainsVariantNPos
00876     : absl::negation<std::is_same<  // NOLINT
00877           absl::integer_sequence<bool, 0 <= Is...>,
00878           absl::integer_sequence<bool, Is != absl::variant_npos...>>> {};
00879 
00880 template <class Op, class... QualifiedVariants>
00881 using RawVisitResult =
00882     absl::result_of_t<Op(VariantAccessResult<0, QualifiedVariants>...)>;
00883 
00884 // NOTE: The spec requires that all return-paths yield the same type and is not
00885 // SFINAE-friendly, so we can deduce the return type by examining the first
00886 // result. If it's not callable, then we get an error, but are compliant and
00887 // fast to compile.
00888 // TODO(calabrese) Possibly rewrite in a way that yields better compile errors
00889 // at the cost of longer compile-times.
00890 template <class Op, class... QualifiedVariants>
00891 struct VisitResultImpl {
00892   using type =
00893       absl::result_of_t<Op(VariantAccessResult<0, QualifiedVariants>...)>;
00894 };
00895 
00896 // Done in two steps intentionally so that we don't cause substitution to fail.
00897 template <class Op, class... QualifiedVariants>
00898 using VisitResult = typename VisitResultImpl<Op, QualifiedVariants...>::type;
00899 
00900 template <class Op, class... QualifiedVariants>
00901 struct PerformVisitation {
00902   using ReturnType = VisitResult<Op, QualifiedVariants...>;
00903 
00904   template <std::size_t... Is>
00905   constexpr ReturnType operator()(SizeT<Is>... indices) const {
00906     return Run(typename ContainsVariantNPos<Is...>::type{},
00907                absl::index_sequence_for<QualifiedVariants...>(), indices...);
00908   }
00909 
00910   template <std::size_t... TupIs, std::size_t... Is>
00911   constexpr ReturnType Run(std::false_type /*has_valueless*/,
00912                            index_sequence<TupIs...>, SizeT<Is>...) const {
00913     static_assert(
00914         std::is_same<ReturnType,
00915                      absl::result_of_t<Op(VariantAccessResult<
00916                                           Is, QualifiedVariants>...)>>::value,
00917         "All visitation overloads must have the same return type.");
00918     return absl::base_internal::Invoke(
00919         absl::forward<Op>(op),
00920         VariantCoreAccess::Access<Is>(
00921             absl::forward<QualifiedVariants>(std::get<TupIs>(variant_tup)))...);
00922   }
00923 
00924   template <std::size_t... TupIs, std::size_t... Is>
00925   [[noreturn]] ReturnType Run(std::true_type /*has_valueless*/,
00926                               index_sequence<TupIs...>, SizeT<Is>...) const {
00927     absl::variant_internal::ThrowBadVariantAccess();
00928   }
00929 
00930   // TODO(calabrese) Avoid using a tuple, which causes lots of instantiations
00931   // Attempts using lambda variadic captures fail on current GCC.
00932   std::tuple<QualifiedVariants&&...> variant_tup;
00933   Op&& op;
00934 };
00935 
00936 template <class... T>
00937 union Union;
00938 
00939 // We want to allow for variant<> to be trivial. For that, we need the default
00940 // constructor to be trivial, which means we can't define it ourselves.
00941 // Instead, we use a non-default constructor that takes NoopConstructorTag
00942 // that doesn't affect the triviality of the types.
00943 struct NoopConstructorTag {};
00944 
00945 template <std::size_t I>
00946 struct EmplaceTag {};
00947 
00948 template <>
00949 union Union<> {
00950   constexpr explicit Union(NoopConstructorTag) noexcept {}
00951 };
00952 
00953 // Suppress bogus warning on MSVC: MSVC complains that Union<T...> has a defined
00954 // deleted destructor from the `std::is_destructible` check below.
00955 #ifdef _MSC_VER
00956 #pragma warning(push)
00957 #pragma warning(disable : 4624)
00958 #endif  // _MSC_VER
00959 
00960 template <class Head, class... Tail>
00961 union Union<Head, Tail...> {
00962   using TailUnion = Union<Tail...>;
00963 
00964   explicit constexpr Union(NoopConstructorTag /*tag*/) noexcept
00965       : tail(NoopConstructorTag()) {}
00966 
00967   template <class... P>
00968   explicit constexpr Union(EmplaceTag<0>, P&&... args)
00969       : head(absl::forward<P>(args)...) {}
00970 
00971   template <std::size_t I, class... P>
00972   explicit constexpr Union(EmplaceTag<I>, P&&... args)
00973       : tail(EmplaceTag<I - 1>{}, absl::forward<P>(args)...) {}
00974 
00975   Head head;
00976   TailUnion tail;
00977 };
00978 
00979 #ifdef _MSC_VER
00980 #pragma warning(pop)
00981 #endif  // _MSC_VER
00982 
00983 // TODO(calabrese) Just contain a Union in this union (certain configs fail).
00984 template <class... T>
00985 union DestructibleUnionImpl;
00986 
00987 template <>
00988 union DestructibleUnionImpl<> {
00989   constexpr explicit DestructibleUnionImpl(NoopConstructorTag) noexcept {}
00990 };
00991 
00992 template <class Head, class... Tail>
00993 union DestructibleUnionImpl<Head, Tail...> {
00994   using TailUnion = DestructibleUnionImpl<Tail...>;
00995 
00996   explicit constexpr DestructibleUnionImpl(NoopConstructorTag /*tag*/) noexcept
00997       : tail(NoopConstructorTag()) {}
00998 
00999   template <class... P>
01000   explicit constexpr DestructibleUnionImpl(EmplaceTag<0>, P&&... args)
01001       : head(absl::forward<P>(args)...) {}
01002 
01003   template <std::size_t I, class... P>
01004   explicit constexpr DestructibleUnionImpl(EmplaceTag<I>, P&&... args)
01005       : tail(EmplaceTag<I - 1>{}, absl::forward<P>(args)...) {}
01006 
01007   ~DestructibleUnionImpl() {}
01008 
01009   Head head;
01010   TailUnion tail;
01011 };
01012 
01013 // This union type is destructible even if one or more T are not trivially
01014 // destructible. In the case that all T are trivially destructible, then so is
01015 // this resultant type.
01016 template <class... T>
01017 using DestructibleUnion =
01018     absl::conditional_t<std::is_destructible<Union<T...>>::value, Union<T...>,
01019                         DestructibleUnionImpl<T...>>;
01020 
01021 // Deepest base, containing the actual union and the discriminator
01022 template <class H, class... T>
01023 class VariantStateBase {
01024  protected:
01025   using Variant = variant<H, T...>;
01026 
01027   template <class LazyH = H,
01028             class ConstructibleH = absl::enable_if_t<
01029                 std::is_default_constructible<LazyH>::value, LazyH>>
01030   constexpr VariantStateBase() noexcept(
01031       std::is_nothrow_default_constructible<ConstructibleH>::value)
01032       : state_(EmplaceTag<0>()), index_(0) {}
01033 
01034   template <std::size_t I, class... P>
01035   explicit constexpr VariantStateBase(EmplaceTag<I> tag, P&&... args)
01036       : state_(tag, absl::forward<P>(args)...), index_(I) {}
01037 
01038   explicit constexpr VariantStateBase(NoopConstructorTag)
01039       : state_(NoopConstructorTag()), index_(variant_npos) {}
01040 
01041   void destroy() {}  // Does nothing (shadowed in child if non-trivial)
01042 
01043   DestructibleUnion<H, T...> state_;
01044   std::size_t index_;
01045 };
01046 
01047 using absl::internal::identity;
01048 
01049 // OverloadSet::Overload() is a unary function which is overloaded to
01050 // take any of the element types of the variant, by reference-to-const.
01051 // The return type of the overload on T is identity<T>, so that you
01052 // can statically determine which overload was called.
01053 //
01054 // Overload() is not defined, so it can only be called in unevaluated
01055 // contexts.
01056 template <typename... Ts>
01057 struct OverloadSet;
01058 
01059 template <typename T, typename... Ts>
01060 struct OverloadSet<T, Ts...> : OverloadSet<Ts...> {
01061   using Base = OverloadSet<Ts...>;
01062   static identity<T> Overload(const T&);
01063   using Base::Overload;
01064 };
01065 
01066 template <>
01067 struct OverloadSet<> {
01068   // For any case not handled above.
01069   static void Overload(...);
01070 };
01071 
01072 template <class T>
01073 using LessThanResult = decltype(std::declval<T>() < std::declval<T>());
01074 
01075 template <class T>
01076 using GreaterThanResult = decltype(std::declval<T>() > std::declval<T>());
01077 
01078 template <class T>
01079 using LessThanOrEqualResult = decltype(std::declval<T>() <= std::declval<T>());
01080 
01081 template <class T>
01082 using GreaterThanOrEqualResult =
01083     decltype(std::declval<T>() >= std::declval<T>());
01084 
01085 template <class T>
01086 using EqualResult = decltype(std::declval<T>() == std::declval<T>());
01087 
01088 template <class T>
01089 using NotEqualResult = decltype(std::declval<T>() != std::declval<T>());
01090 
01091 using type_traits_internal::is_detected_convertible;
01092 
01093 template <class... T>
01094 using RequireAllHaveEqualT = absl::enable_if_t<
01095     absl::conjunction<is_detected_convertible<bool, EqualResult, T>...>::value,
01096     bool>;
01097 
01098 template <class... T>
01099 using RequireAllHaveNotEqualT =
01100     absl::enable_if_t<absl::conjunction<is_detected_convertible<
01101                           bool, NotEqualResult, T>...>::value,
01102                       bool>;
01103 
01104 template <class... T>
01105 using RequireAllHaveLessThanT =
01106     absl::enable_if_t<absl::conjunction<is_detected_convertible<
01107                           bool, LessThanResult, T>...>::value,
01108                       bool>;
01109 
01110 template <class... T>
01111 using RequireAllHaveLessThanOrEqualT =
01112     absl::enable_if_t<absl::conjunction<is_detected_convertible<
01113                           bool, LessThanOrEqualResult, T>...>::value,
01114                       bool>;
01115 
01116 template <class... T>
01117 using RequireAllHaveGreaterThanOrEqualT =
01118     absl::enable_if_t<absl::conjunction<is_detected_convertible<
01119                           bool, GreaterThanOrEqualResult, T>...>::value,
01120                       bool>;
01121 
01122 template <class... T>
01123 using RequireAllHaveGreaterThanT =
01124     absl::enable_if_t<absl::conjunction<is_detected_convertible<
01125                           bool, GreaterThanResult, T>...>::value,
01126                       bool>;
01127 
01128 // Helper template containing implementations details of variant that can't go
01129 // in the private section. For convenience, this takes the variant type as a
01130 // single template parameter.
01131 template <typename T>
01132 struct VariantHelper;
01133 
01134 template <typename... Ts>
01135 struct VariantHelper<variant<Ts...>> {
01136   // Type metafunction which returns the element type selected if
01137   // OverloadSet::Overload() is well-formed when called with argument type U.
01138   template <typename U>
01139   using BestMatch = decltype(
01140       variant_internal::OverloadSet<Ts...>::Overload(std::declval<U>()));
01141 
01142   // Type metafunction which returns true if OverloadSet::Overload() is
01143   // well-formed when called with argument type U.
01144   // CanAccept can't be just an alias because there is a MSVC bug on parameter
01145   // pack expansion involving decltype.
01146   template <typename U>
01147   struct CanAccept :
01148       std::integral_constant<bool, !std::is_void<BestMatch<U>>::value> {};
01149 
01150   // Type metafunction which returns true if Other is an instantiation of
01151   // variant, and variants's converting constructor from Other will be
01152   // well-formed. We will use this to remove constructors that would be
01153   // ill-formed from the overload set.
01154   template <typename Other>
01155   struct CanConvertFrom;
01156 
01157   template <typename... Us>
01158   struct CanConvertFrom<variant<Us...>>
01159       : public absl::conjunction<CanAccept<Us>...> {};
01160 };
01161 
01162 // A type with nontrivial copy ctor and trivial move ctor.
01163 struct TrivialMoveOnly {
01164   TrivialMoveOnly(TrivialMoveOnly&&) = default;
01165 };
01166 
01167 // Trait class to detect whether a type is trivially move constructible.
01168 // A union's defaulted copy/move constructor is deleted if any variant member's
01169 // copy/move constructor is nontrivial.
01170 template <typename T>
01171 struct IsTriviallyMoveConstructible:
01172   std::is_move_constructible<Union<T, TrivialMoveOnly>> {};
01173 
01174 // To guarantee triviality of all special-member functions that can be trivial,
01175 // we use a chain of conditional bases for each one.
01176 // The order of inheritance of bases from child to base are logically:
01177 //
01178 // variant
01179 // VariantCopyAssignBase
01180 // VariantMoveAssignBase
01181 // VariantCopyBase
01182 // VariantMoveBase
01183 // VariantStateBaseDestructor
01184 // VariantStateBase
01185 //
01186 // Note that there is a separate branch at each base that is dependent on
01187 // whether or not that corresponding special-member-function can be trivial in
01188 // the resultant variant type.
01189 
01190 template <class... T>
01191 class VariantStateBaseDestructorNontrivial;
01192 
01193 template <class... T>
01194 class VariantMoveBaseNontrivial;
01195 
01196 template <class... T>
01197 class VariantCopyBaseNontrivial;
01198 
01199 template <class... T>
01200 class VariantMoveAssignBaseNontrivial;
01201 
01202 template <class... T>
01203 class VariantCopyAssignBaseNontrivial;
01204 
01205 // Base that is dependent on whether or not the destructor can be trivial.
01206 template <class... T>
01207 using VariantStateBaseDestructor =
01208     absl::conditional_t<std::is_destructible<Union<T...>>::value,
01209                         VariantStateBase<T...>,
01210                         VariantStateBaseDestructorNontrivial<T...>>;
01211 
01212 // Base that is dependent on whether or not the move-constructor can be
01213 // implicitly generated by the compiler (trivial or deleted).
01214 // Previously we were using `std::is_move_constructible<Union<T...>>` to check
01215 // whether all Ts have trivial move constructor, but it ran into a GCC bug:
01216 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84866
01217 // So we have to use a different approach (i.e. `HasTrivialMoveConstructor`) to
01218 // work around the bug.
01219 template <class... T>
01220 using VariantMoveBase = absl::conditional_t<
01221     absl::disjunction<
01222         absl::negation<absl::conjunction<std::is_move_constructible<T>...>>,
01223         absl::conjunction<IsTriviallyMoveConstructible<T>...>>::value,
01224     VariantStateBaseDestructor<T...>, VariantMoveBaseNontrivial<T...>>;
01225 
01226 // Base that is dependent on whether or not the copy-constructor can be trivial.
01227 template <class... T>
01228 using VariantCopyBase = absl::conditional_t<
01229     absl::disjunction<
01230         absl::negation<absl::conjunction<std::is_copy_constructible<T>...>>,
01231         std::is_copy_constructible<Union<T...>>>::value,
01232     VariantMoveBase<T...>, VariantCopyBaseNontrivial<T...>>;
01233 
01234 // Base that is dependent on whether or not the move-assign can be trivial.
01235 template <class... T>
01236 using VariantMoveAssignBase = absl::conditional_t<
01237     absl::disjunction<
01238         absl::conjunction<absl::is_move_assignable<Union<T...>>,
01239                           std::is_move_constructible<Union<T...>>,
01240                           std::is_destructible<Union<T...>>>,
01241         absl::negation<absl::conjunction<std::is_move_constructible<T>...,
01242                                          // Note: We're not qualifying this with
01243                                          // absl:: because it doesn't compile
01244                                          // under MSVC.
01245                                          is_move_assignable<T>...>>>::value,
01246     VariantCopyBase<T...>, VariantMoveAssignBaseNontrivial<T...>>;
01247 
01248 // Base that is dependent on whether or not the copy-assign can be trivial.
01249 template <class... T>
01250 using VariantCopyAssignBase = absl::conditional_t<
01251     absl::disjunction<
01252         absl::conjunction<absl::is_copy_assignable<Union<T...>>,
01253                           std::is_copy_constructible<Union<T...>>,
01254                           std::is_destructible<Union<T...>>>,
01255         absl::negation<absl::conjunction<std::is_copy_constructible<T>...,
01256                                          // Note: We're not qualifying this with
01257                                          // absl:: because it doesn't compile
01258                                          // under MSVC.
01259                                          is_copy_assignable<T>...>>>::value,
01260     VariantMoveAssignBase<T...>, VariantCopyAssignBaseNontrivial<T...>>;
01261 
01262 template <class... T>
01263 using VariantBase = VariantCopyAssignBase<T...>;
01264 
01265 template <class... T>
01266 class VariantStateBaseDestructorNontrivial : protected VariantStateBase<T...> {
01267  private:
01268   using Base = VariantStateBase<T...>;
01269 
01270  protected:
01271   using Base::Base;
01272 
01273   VariantStateBaseDestructorNontrivial() = default;
01274   VariantStateBaseDestructorNontrivial(VariantStateBaseDestructorNontrivial&&) =
01275       default;
01276   VariantStateBaseDestructorNontrivial(
01277       const VariantStateBaseDestructorNontrivial&) = default;
01278   VariantStateBaseDestructorNontrivial& operator=(
01279       VariantStateBaseDestructorNontrivial&&) = default;
01280   VariantStateBaseDestructorNontrivial& operator=(
01281       const VariantStateBaseDestructorNontrivial&) = default;
01282 
01283   struct Destroyer {
01284     template <std::size_t I>
01285     void operator()(SizeT<I> i) const {
01286       using Alternative =
01287           typename absl::variant_alternative<I, variant<T...>>::type;
01288       variant_internal::AccessUnion(self->state_, i).~Alternative();
01289     }
01290 
01291     void operator()(SizeT<absl::variant_npos> /*i*/) const {
01292       // This space intentionally left blank
01293     }
01294 
01295     VariantStateBaseDestructorNontrivial* self;
01296   };
01297 
01298   void destroy() { VisitIndices<sizeof...(T)>::Run(Destroyer{this}, index_); }
01299 
01300   ~VariantStateBaseDestructorNontrivial() { destroy(); }
01301 
01302  protected:
01303   using Base::index_;
01304   using Base::state_;
01305 };
01306 
01307 template <class... T>
01308 class VariantMoveBaseNontrivial : protected VariantStateBaseDestructor<T...> {
01309  private:
01310   using Base = VariantStateBaseDestructor<T...>;
01311 
01312  protected:
01313   using Base::Base;
01314 
01315   struct Construct {
01316     template <std::size_t I>
01317     void operator()(SizeT<I> i) const {
01318       using Alternative =
01319           typename absl::variant_alternative<I, variant<T...>>::type;
01320       ::new (static_cast<void*>(&self->state_)) Alternative(
01321           variant_internal::AccessUnion(absl::move(other->state_), i));
01322     }
01323 
01324     void operator()(SizeT<absl::variant_npos> /*i*/) const {}
01325 
01326     VariantMoveBaseNontrivial* self;
01327     VariantMoveBaseNontrivial* other;
01328   };
01329 
01330   VariantMoveBaseNontrivial() = default;
01331   VariantMoveBaseNontrivial(VariantMoveBaseNontrivial&& other) noexcept(
01332       absl::conjunction<std::is_nothrow_move_constructible<T>...>::value)
01333       : Base(NoopConstructorTag()) {
01334     VisitIndices<sizeof...(T)>::Run(Construct{this, &other}, other.index_);
01335     index_ = other.index_;
01336   }
01337 
01338   VariantMoveBaseNontrivial(VariantMoveBaseNontrivial const&) = default;
01339 
01340   VariantMoveBaseNontrivial& operator=(VariantMoveBaseNontrivial&&) = default;
01341   VariantMoveBaseNontrivial& operator=(VariantMoveBaseNontrivial const&) =
01342       default;
01343 
01344  protected:
01345   using Base::index_;
01346   using Base::state_;
01347 };
01348 
01349 template <class... T>
01350 class VariantCopyBaseNontrivial : protected VariantMoveBase<T...> {
01351  private:
01352   using Base = VariantMoveBase<T...>;
01353 
01354  protected:
01355   using Base::Base;
01356 
01357   VariantCopyBaseNontrivial() = default;
01358   VariantCopyBaseNontrivial(VariantCopyBaseNontrivial&&) = default;
01359 
01360   struct Construct {
01361     template <std::size_t I>
01362     void operator()(SizeT<I> i) const {
01363       using Alternative =
01364           typename absl::variant_alternative<I, variant<T...>>::type;
01365       ::new (static_cast<void*>(&self->state_))
01366           Alternative(variant_internal::AccessUnion(other->state_, i));
01367     }
01368 
01369     void operator()(SizeT<absl::variant_npos> /*i*/) const {}
01370 
01371     VariantCopyBaseNontrivial* self;
01372     const VariantCopyBaseNontrivial* other;
01373   };
01374 
01375   VariantCopyBaseNontrivial(VariantCopyBaseNontrivial const& other)
01376       : Base(NoopConstructorTag()) {
01377     VisitIndices<sizeof...(T)>::Run(Construct{this, &other}, other.index_);
01378     index_ = other.index_;
01379   }
01380 
01381   VariantCopyBaseNontrivial& operator=(VariantCopyBaseNontrivial&&) = default;
01382   VariantCopyBaseNontrivial& operator=(VariantCopyBaseNontrivial const&) =
01383       default;
01384 
01385  protected:
01386   using Base::index_;
01387   using Base::state_;
01388 };
01389 
01390 template <class... T>
01391 class VariantMoveAssignBaseNontrivial : protected VariantCopyBase<T...> {
01392   friend struct VariantCoreAccess;
01393 
01394  private:
01395   using Base = VariantCopyBase<T...>;
01396 
01397  protected:
01398   using Base::Base;
01399 
01400   VariantMoveAssignBaseNontrivial() = default;
01401   VariantMoveAssignBaseNontrivial(VariantMoveAssignBaseNontrivial&&) = default;
01402   VariantMoveAssignBaseNontrivial(const VariantMoveAssignBaseNontrivial&) =
01403       default;
01404   VariantMoveAssignBaseNontrivial& operator=(
01405       VariantMoveAssignBaseNontrivial const&) = default;
01406 
01407     VariantMoveAssignBaseNontrivial&
01408     operator=(VariantMoveAssignBaseNontrivial&& other) noexcept(
01409         absl::conjunction<std::is_nothrow_move_constructible<T>...,
01410                           std::is_nothrow_move_assignable<T>...>::value) {
01411       VisitIndices<sizeof...(T)>::Run(
01412           VariantCoreAccess::MakeMoveAssignVisitor(this, &other), other.index_);
01413       return *this;
01414     }
01415 
01416  protected:
01417   using Base::index_;
01418   using Base::state_;
01419 };
01420 
01421 template <class... T>
01422 class VariantCopyAssignBaseNontrivial : protected VariantMoveAssignBase<T...> {
01423   friend struct VariantCoreAccess;
01424 
01425  private:
01426   using Base = VariantMoveAssignBase<T...>;
01427 
01428  protected:
01429   using Base::Base;
01430 
01431   VariantCopyAssignBaseNontrivial() = default;
01432   VariantCopyAssignBaseNontrivial(VariantCopyAssignBaseNontrivial&&) = default;
01433   VariantCopyAssignBaseNontrivial(const VariantCopyAssignBaseNontrivial&) =
01434       default;
01435   VariantCopyAssignBaseNontrivial& operator=(
01436       VariantCopyAssignBaseNontrivial&&) = default;
01437 
01438     VariantCopyAssignBaseNontrivial& operator=(
01439         const VariantCopyAssignBaseNontrivial& other) {
01440       VisitIndices<sizeof...(T)>::Run(
01441           VariantCoreAccess::MakeCopyAssignVisitor(this, other), other.index_);
01442       return *this;
01443     }
01444 
01445  protected:
01446   using Base::index_;
01447   using Base::state_;
01448 };
01449 
01451 // Visitors for Comparison Operations //
01453 
01454 template <class... Types>
01455 struct EqualsOp {
01456   const variant<Types...>* v;
01457   const variant<Types...>* w;
01458 
01459   constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
01460     return true;
01461   }
01462 
01463   template <std::size_t I>
01464   constexpr bool operator()(SizeT<I> /*v_i*/) const {
01465     return VariantCoreAccess::Access<I>(*v) == VariantCoreAccess::Access<I>(*w);
01466   }
01467 };
01468 
01469 template <class... Types>
01470 struct NotEqualsOp {
01471   const variant<Types...>* v;
01472   const variant<Types...>* w;
01473 
01474   constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
01475     return false;
01476   }
01477 
01478   template <std::size_t I>
01479   constexpr bool operator()(SizeT<I> /*v_i*/) const {
01480     return VariantCoreAccess::Access<I>(*v) != VariantCoreAccess::Access<I>(*w);
01481   }
01482 };
01483 
01484 template <class... Types>
01485 struct LessThanOp {
01486   const variant<Types...>* v;
01487   const variant<Types...>* w;
01488 
01489   constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
01490     return false;
01491   }
01492 
01493   template <std::size_t I>
01494   constexpr bool operator()(SizeT<I> /*v_i*/) const {
01495     return VariantCoreAccess::Access<I>(*v) < VariantCoreAccess::Access<I>(*w);
01496   }
01497 };
01498 
01499 template <class... Types>
01500 struct GreaterThanOp {
01501   const variant<Types...>* v;
01502   const variant<Types...>* w;
01503 
01504   constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
01505     return false;
01506   }
01507 
01508   template <std::size_t I>
01509   constexpr bool operator()(SizeT<I> /*v_i*/) const {
01510     return VariantCoreAccess::Access<I>(*v) > VariantCoreAccess::Access<I>(*w);
01511   }
01512 };
01513 
01514 template <class... Types>
01515 struct LessThanOrEqualsOp {
01516   const variant<Types...>* v;
01517   const variant<Types...>* w;
01518 
01519   constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
01520     return true;
01521   }
01522 
01523   template <std::size_t I>
01524   constexpr bool operator()(SizeT<I> /*v_i*/) const {
01525     return VariantCoreAccess::Access<I>(*v) <= VariantCoreAccess::Access<I>(*w);
01526   }
01527 };
01528 
01529 template <class... Types>
01530 struct GreaterThanOrEqualsOp {
01531   const variant<Types...>* v;
01532   const variant<Types...>* w;
01533 
01534   constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
01535     return true;
01536   }
01537 
01538   template <std::size_t I>
01539   constexpr bool operator()(SizeT<I> /*v_i*/) const {
01540     return VariantCoreAccess::Access<I>(*v) >= VariantCoreAccess::Access<I>(*w);
01541   }
01542 };
01543 
01544 // Precondition: v.index() == w.index();
01545 template <class... Types>
01546 struct SwapSameIndex {
01547   variant<Types...>* v;
01548   variant<Types...>* w;
01549   template <std::size_t I>
01550   void operator()(SizeT<I>) const {
01551     type_traits_internal::Swap(VariantCoreAccess::Access<I>(*v),
01552                                VariantCoreAccess::Access<I>(*w));
01553   }
01554 
01555   void operator()(SizeT<variant_npos>) const {}
01556 };
01557 
01558 // TODO(calabrese) do this from a different namespace for proper adl usage
01559 template <class... Types>
01560 struct Swap {
01561   variant<Types...>* v;
01562   variant<Types...>* w;
01563 
01564   void generic_swap() const {
01565     variant<Types...> tmp(std::move(*w));
01566     VariantCoreAccess::Destroy(*w);
01567     VariantCoreAccess::InitFrom(*w, std::move(*v));
01568     VariantCoreAccess::Destroy(*v);
01569     VariantCoreAccess::InitFrom(*v, std::move(tmp));
01570   }
01571 
01572   void operator()(SizeT<absl::variant_npos> /*w_i*/) const {
01573     if (!v->valueless_by_exception()) {
01574       generic_swap();
01575     }
01576   }
01577 
01578   template <std::size_t Wi>
01579   void operator()(SizeT<Wi> /*w_i*/) {
01580     if (v->index() == Wi) {
01581       VisitIndices<sizeof...(Types)>::Run(SwapSameIndex<Types...>{v, w}, Wi);
01582     } else {
01583       generic_swap();
01584     }
01585   }
01586 };
01587 
01588 template <typename Variant, typename = void, typename... Ts>
01589 struct VariantHashBase {
01590   VariantHashBase() = delete;
01591   VariantHashBase(const VariantHashBase&) = delete;
01592   VariantHashBase(VariantHashBase&&) = delete;
01593   VariantHashBase& operator=(const VariantHashBase&) = delete;
01594   VariantHashBase& operator=(VariantHashBase&&) = delete;
01595 };
01596 
01597 struct VariantHashVisitor {
01598   template <typename T>
01599   size_t operator()(const T& t) {
01600     return std::hash<T>{}(t);
01601   }
01602 };
01603 
01604 template <typename Variant, typename... Ts>
01605 struct VariantHashBase<Variant,
01606                        absl::enable_if_t<absl::conjunction<
01607                            type_traits_internal::IsHashable<Ts>...>::value>,
01608                        Ts...> {
01609   using argument_type = Variant;
01610   using result_type = size_t;
01611   size_t operator()(const Variant& var) const {
01612     type_traits_internal::AssertHashEnabled<Ts...>();
01613     if (var.valueless_by_exception()) {
01614       return 239799884;
01615     }
01616     size_t result = VisitIndices<variant_size<Variant>::value>::Run(
01617         PerformVisitation<VariantHashVisitor, const Variant&>{
01618             std::forward_as_tuple(var), VariantHashVisitor{}},
01619         var.index());
01620     // Combine the index and the hash result in order to distinguish
01621     // std::variant<int, int> holding the same value as different alternative.
01622     return result ^ var.index();
01623   }
01624 };
01625 
01626 }  // namespace variant_internal
01627 }  // namespace absl
01628 
01629 #endif  // !defined(ABSL_HAVE_STD_VARIANT)
01630 #endif  // ABSL_TYPES_variant_internal_H_


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