File indexing completed on 2025-12-16 09:41:08
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
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
0060 template <std::size_t I, class T>
0061 struct VariantAlternativeSfinae {};
0062
0063
0064
0065
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
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
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
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
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
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&& ) {
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
0288
0289
0290
0291
0292 ABSL_INTERNAL_INLINE_CONSTEXPR(std::size_t, MaxUnrolledVisitCases, 33);
0293
0294
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<true> {
0303 template <class Op, std::size_t I>
0304 using Apply = ReachableSwitchCase<Op, I>;
0305 };
0306
0307
0308
0309
0310
0311
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
0321
0322
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
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
0433
0434
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
0452
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
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
0472
0473
0474 template <class Op>
0475 struct FlattenedOp {
0476 template <std::size_t I>
0477 VisitIndicesResultT<Op, decltype(EndIndices)...> operator()(
0478 SizeT<I> ) && {
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
0504
0505
0506
0507
0508
0509
0510
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
0525
0526 #ifdef _MSC_VER
0527 #pragma warning(push)
0528 #pragma warning(disable : 4172)
0529 #endif
0530
0531
0532
0533
0534
0535 template <class Self, std::size_t I>
0536 inline VariantAccessResult<I, Self> AccessUnion(Self&& self, SizeT<I> ) {
0537 return reinterpret_cast<VariantAccessResult<I, Self>>(self);
0538 }
0539
0540 #ifdef _MSC_VER
0541 #pragma warning(pop)
0542 #endif
0543
0544 template <class T>
0545 void DeducedDestroy(T& self) {
0546 self.~T();
0547 }
0548
0549
0550
0551
0552
0553 struct VariantCoreAccess {
0554 template <class VariantType>
0555 static typename VariantType::Variant& Derived(VariantType& self) {
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) {
0562 return static_cast<const typename VariantType::Variant&>(self);
0563 }
0564
0565 template <class VariantType>
0566 static void Destroy(VariantType& self) {
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) {
0573 self.index_ = i;
0574 }
0575
0576 template <class Variant>
0577 static void InitFrom(Variant& self, Variant&& other) {
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
0586 template <std::size_t I, class Variant>
0587 static VariantAccessResult<I, Variant> Access(Variant&& self) {
0588
0589
0590
0591
0592 return static_cast<VariantAccessResult<I, Variant>>(
0593 variant_internal::AccessUnion(self.state_, SizeT<I>()));
0594 }
0595
0596
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
0607 template <class VType>
0608 struct MoveAssignVisitor {
0609 using DerivedType = typename VType::Variant;
0610 template <std::size_t NewIndex>
0611 void operator()(SizeT<NewIndex> ) 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> ) 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
0635 template <class VType>
0636 struct CopyAssignVisitor {
0637 using DerivedType = typename VType::Variant;
0638 template <std::size_t NewIndex>
0639 void operator()(SizeT<NewIndex> ) 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> ) 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
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>
0674 ) const {
0675 Access<NewIndex::value>(*left) = std::forward<QualifiedNew>(other);
0676 }
0677
0678 template <std::size_t OldIndex>
0679 void operator()(SizeT<OldIndex>
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
0689
0690
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
0707
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> ) 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> ) const {
0730
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
0782 template <class T, std::size_t CurrIndex>
0783 struct UnambiguousIndexOfImpl<variant<>, T, CurrIndex> : SizeT<CurrIndex> {};
0784
0785
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
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 >
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
0823
0824
0825
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
0839
0840
0841 static SizeT<I> Run(const H&, SizeT<I>);
0842 static SizeT<I> Run(H&&, SizeT<I>);
0843 };
0844
0845
0846
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<
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
0876
0877
0878
0879
0880
0881 template <class Op, class... QualifiedVariants>
0882 struct VisitResultImpl {
0883 using type =
0884 absl::result_of_t<Op(VariantAccessResult<0, QualifiedVariants>...)>;
0885 };
0886
0887
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 ,
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 ,
0917 index_sequence<TupIs...>, SizeT<Is>...) const {
0918 absl::variant_internal::ThrowBadVariantAccess();
0919 }
0920
0921
0922
0923 std::tuple<QualifiedVariants&&...> variant_tup;
0924 Op&& op;
0925 };
0926
0927 template <class... T>
0928 union Union;
0929
0930
0931
0932
0933
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
0945
0946 #ifdef _MSC_VER
0947 #pragma warning(push)
0948 #pragma warning(disable : 4624)
0949 #endif
0950
0951 template <class Head, class... Tail>
0952 union Union<Head, Tail...> {
0953 using TailUnion = Union<Tail...>;
0954
0955 explicit constexpr Union(NoopConstructorTag ) 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
0973
0974
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 ) 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
1005
1006
1007 template <class... T>
1008 using DestructibleUnion =
1009 absl::conditional_t<std::is_destructible<Union<T...>>::value, Union<T...>,
1010 DestructibleUnionImpl<T...>>;
1011
1012
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() {}
1033
1034 DestructibleUnion<H, T...> state_;
1035 std::size_t index_;
1036 };
1037
1038 using absl::internal::type_identity;
1039
1040
1041
1042
1043
1044
1045
1046
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
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
1120
1121
1122 template <typename T>
1123 struct VariantHelper;
1124
1125 template <typename... Ts>
1126 struct VariantHelper<variant<Ts...>> {
1127
1128
1129 template <typename U>
1130 using BestMatch = decltype(variant_internal::OverloadSet<Ts...>::Overload(
1131 std::declval<U>()));
1132
1133
1134
1135
1136
1137 template <typename U>
1138 struct CanAccept
1139 : std::integral_constant<bool, !std::is_void<BestMatch<U>>::value> {};
1140
1141
1142
1143
1144
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
1154 struct TrivialMoveOnly {
1155 TrivialMoveOnly(TrivialMoveOnly&&) = default;
1156 };
1157
1158
1159
1160
1161 template <typename T>
1162 struct IsTriviallyMoveConstructible
1163 : std::is_move_constructible<Union<T, TrivialMoveOnly>> {};
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
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
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
1204
1205
1206
1207
1208
1209
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
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
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
1234
1235
1236 is_move_assignable<T>...>>>::value,
1237 VariantCopyBase<T...>, VariantMoveAssignBaseNontrivial<T...>>;
1238
1239
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
1248
1249
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> ) const {
1283
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> ) 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> ) 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
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> ) const {
1451 return true;
1452 }
1453
1454 template <std::size_t I>
1455 constexpr bool operator()(SizeT<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> ) const {
1466 return false;
1467 }
1468
1469 template <std::size_t I>
1470 constexpr bool operator()(SizeT<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> ) const {
1481 return false;
1482 }
1483
1484 template <std::size_t I>
1485 constexpr bool operator()(SizeT<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> ) const {
1496 return false;
1497 }
1498
1499 template <std::size_t I>
1500 constexpr bool operator()(SizeT<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> ) const {
1511 return true;
1512 }
1513
1514 template <std::size_t I>
1515 constexpr bool operator()(SizeT<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> ) const {
1526 return true;
1527 }
1528
1529 template <std::size_t I>
1530 constexpr bool operator()(SizeT<I> ) const {
1531 return VariantCoreAccess::Access<I>(*v) >= VariantCoreAccess::Access<I>(*w);
1532 }
1533 };
1534
1535
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
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> ) const {
1564 if (!v->valueless_by_exception()) {
1565 generic_swap();
1566 }
1567 }
1568
1569 template <std::size_t Wi>
1570 void operator()(SizeT<Wi> ) {
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
1612
1613 return result ^ var.index();
1614 }
1615 };
1616
1617 }
1618 ABSL_NAMESPACE_END
1619 }
1620
1621 #endif
1622 #endif