diff options
author | Vincent Ambo <mail@tazj.in> | 2022-02-07T23·05+0300 |
---|---|---|
committer | clbot <clbot@tvl.fyi> | 2022-02-07T23·09+0000 |
commit | 5aa5d282eac56a21e74611c1cdbaa97bb5db2dca (patch) | |
tree | 8cc5dce8157a1470ff76719dd15d65f648a05522 /third_party/abseil_cpp/absl/types/internal | |
parent | a25675804c4f429fab5ee5201fe25e89865dfd13 (diff) |
chore(3p/abseil_cpp): unvendor abseil_cpp r/3786
we weren't actually using these sources anymore, okay? Change-Id: If701571d9716de308d3512e1eb22c35db0877a66 Reviewed-on: https://cl.tvl.fyi/c/depot/+/5248 Tested-by: BuildkiteCI Reviewed-by: grfn <grfn@gws.fyi> Autosubmit: tazjin <tazjin@tvl.su>
Diffstat (limited to 'third_party/abseil_cpp/absl/types/internal')
11 files changed, 0 insertions, 8139 deletions
diff --git a/third_party/abseil_cpp/absl/types/internal/conformance_aliases.h b/third_party/abseil_cpp/absl/types/internal/conformance_aliases.h deleted file mode 100644 index 0cc6884e309e..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/conformance_aliases.h +++ /dev/null @@ -1,447 +0,0 @@ -// Copyright 2018 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------- -// regularity_aliases.h -// ----------------------------------------------------------------------------- -// -// This file contains type aliases of common ConformanceProfiles and Archetypes -// so that they can be directly used by name without creating them from scratch. - -#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_ALIASES_H_ -#define ABSL_TYPES_INTERNAL_CONFORMANCE_ALIASES_H_ - -#include "absl/types/internal/conformance_archetype.h" -#include "absl/types/internal/conformance_profile.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace types_internal { - -// Creates both a Profile and a corresponding Archetype with root name "name". -#define ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(name, ...) \ - struct name##Profile : __VA_ARGS__ {}; \ - \ - using name##Archetype = ::absl::types_internal::Archetype<name##Profile>; \ - \ - template <class AbslInternalProfileTag> \ - using name##Archetype##_ = ::absl::types_internal::Archetype< \ - ::absl::types_internal::StrongProfileTypedef<name##Profile, \ - AbslInternalProfileTag>> - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasTrivialDefaultConstructor, - ConformanceProfile<default_constructible::trivial>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowDefaultConstructor, - ConformanceProfile<default_constructible::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasDefaultConstructor, ConformanceProfile<default_constructible::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasTrivialMoveConstructor, ConformanceProfile<default_constructible::maybe, - move_constructible::trivial>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowMoveConstructor, ConformanceProfile<default_constructible::maybe, - move_constructible::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasMoveConstructor, - ConformanceProfile<default_constructible::maybe, move_constructible::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasTrivialCopyConstructor, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::trivial>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowCopyConstructor, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasCopyConstructor, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasTrivialMoveAssign, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::trivial>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowMoveAssign, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasMoveAssign, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasTrivialCopyAssign, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::trivial>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowCopyAssign, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasCopyAssign, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasTrivialDestructor, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::trivial>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowDestructor, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasDestructor, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowEquality, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, - equality_comparable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasEquality, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, - equality_comparable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowInequality, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, - equality_comparable::maybe, - inequality_comparable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasInequality, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, - equality_comparable::maybe, inequality_comparable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowLessThan, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, - equality_comparable::maybe, inequality_comparable::maybe, - less_than_comparable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasLessThan, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, - equality_comparable::maybe, inequality_comparable::maybe, - less_than_comparable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowLessEqual, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, - equality_comparable::maybe, inequality_comparable::maybe, - less_than_comparable::maybe, - less_equal_comparable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasLessEqual, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, - equality_comparable::maybe, inequality_comparable::maybe, - less_than_comparable::maybe, - less_equal_comparable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowGreaterEqual, - ConformanceProfile< - default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, equality_comparable::maybe, - inequality_comparable::maybe, less_than_comparable::maybe, - less_equal_comparable::maybe, greater_equal_comparable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasGreaterEqual, - ConformanceProfile< - default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, equality_comparable::maybe, - inequality_comparable::maybe, less_than_comparable::maybe, - less_equal_comparable::maybe, greater_equal_comparable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowGreaterThan, - ConformanceProfile< - default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, equality_comparable::maybe, - inequality_comparable::maybe, less_than_comparable::maybe, - less_equal_comparable::maybe, greater_equal_comparable::maybe, - greater_than_comparable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasGreaterThan, - ConformanceProfile< - default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, equality_comparable::maybe, - inequality_comparable::maybe, less_than_comparable::maybe, - less_equal_comparable::maybe, greater_equal_comparable::maybe, - greater_than_comparable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowSwap, - ConformanceProfile< - default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, equality_comparable::maybe, - inequality_comparable::maybe, less_than_comparable::maybe, - less_equal_comparable::maybe, greater_equal_comparable::maybe, - greater_than_comparable::maybe, swappable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasSwap, - ConformanceProfile< - default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, equality_comparable::maybe, - inequality_comparable::maybe, less_than_comparable::maybe, - less_equal_comparable::maybe, greater_equal_comparable::maybe, - greater_than_comparable::maybe, swappable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasStdHashSpecialization, - ConformanceProfile< - default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, equality_comparable::maybe, - inequality_comparable::maybe, less_than_comparable::maybe, - less_equal_comparable::maybe, greater_equal_comparable::maybe, - greater_than_comparable::maybe, swappable::maybe, hashable::yes>); - -//////////////////////////////////////////////////////////////////////////////// -//// The remaining aliases are combinations of the previous aliases. //// -//////////////////////////////////////////////////////////////////////////////// - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - Equatable, CombineProfiles<HasEqualityProfile, HasInequalityProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - Comparable, - CombineProfiles<EquatableProfile, HasLessThanProfile, HasLessEqualProfile, - HasGreaterEqualProfile, HasGreaterThanProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - NothrowEquatable, - CombineProfiles<HasNothrowEqualityProfile, HasNothrowInequalityProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - NothrowComparable, - CombineProfiles<NothrowEquatableProfile, HasNothrowLessThanProfile, - HasNothrowLessEqualProfile, HasNothrowGreaterEqualProfile, - HasNothrowGreaterThanProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - Value, - CombineProfiles<HasNothrowMoveConstructorProfile, HasCopyConstructorProfile, - HasNothrowMoveAssignProfile, HasCopyAssignProfile, - HasNothrowDestructorProfile, HasNothrowSwapProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - EquatableValue, CombineProfiles<EquatableProfile, ValueProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - ComparableValue, CombineProfiles<ComparableProfile, ValueProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - DefaultConstructibleValue, - CombineProfiles<HasDefaultConstructorProfile, ValueProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - NothrowMoveConstructible, CombineProfiles<HasNothrowMoveConstructorProfile, - HasNothrowDestructorProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - EquatableNothrowMoveConstructible, - CombineProfiles<EquatableProfile, NothrowMoveConstructibleProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - ComparableNothrowMoveConstructible, - CombineProfiles<ComparableProfile, NothrowMoveConstructibleProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - DefaultConstructibleNothrowMoveConstructible, - CombineProfiles<HasDefaultConstructorProfile, - NothrowMoveConstructibleProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - CopyConstructible, - CombineProfiles<HasNothrowMoveConstructorProfile, HasCopyConstructorProfile, - HasNothrowDestructorProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - EquatableCopyConstructible, - CombineProfiles<EquatableProfile, CopyConstructibleProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - ComparableCopyConstructible, - CombineProfiles<ComparableProfile, CopyConstructibleProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - DefaultConstructibleCopyConstructible, - CombineProfiles<HasDefaultConstructorProfile, CopyConstructibleProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - NothrowMovable, - CombineProfiles<HasNothrowMoveConstructorProfile, - HasNothrowMoveAssignProfile, HasNothrowDestructorProfile, - HasNothrowSwapProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - EquatableNothrowMovable, - CombineProfiles<EquatableProfile, NothrowMovableProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - ComparableNothrowMovable, - CombineProfiles<ComparableProfile, NothrowMovableProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - DefaultConstructibleNothrowMovable, - CombineProfiles<HasDefaultConstructorProfile, NothrowMovableProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - TrivialSpecialMemberFunctions, - CombineProfiles<HasTrivialDefaultConstructorProfile, - HasTrivialMoveConstructorProfile, - HasTrivialCopyConstructorProfile, - HasTrivialMoveAssignProfile, HasTrivialCopyAssignProfile, - HasTrivialDestructorProfile, HasNothrowSwapProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - TriviallyComplete, - CombineProfiles<TrivialSpecialMemberFunctionsProfile, ComparableProfile, - HasStdHashSpecializationProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HashableNothrowMoveConstructible, - CombineProfiles<HasStdHashSpecializationProfile, - NothrowMoveConstructibleProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HashableCopyConstructible, - CombineProfiles<HasStdHashSpecializationProfile, CopyConstructibleProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HashableNothrowMovable, - CombineProfiles<HasStdHashSpecializationProfile, NothrowMovableProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HashableValue, - CombineProfiles<HasStdHashSpecializationProfile, ValueProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - ComparableHashableValue, - CombineProfiles<HashableValueProfile, ComparableProfile>); - -// The "preferred" profiles that we support in Abseil. -template <template <class...> class Receiver> -using ExpandBasicProfiles = - Receiver<NothrowMoveConstructibleProfile, CopyConstructibleProfile, - NothrowMovableProfile, ValueProfile>; - -// The basic profiles except that they are also all Equatable. -template <template <class...> class Receiver> -using ExpandBasicEquatableProfiles = - Receiver<EquatableNothrowMoveConstructibleProfile, - EquatableCopyConstructibleProfile, EquatableNothrowMovableProfile, - EquatableValueProfile>; - -// The basic profiles except that they are also all Comparable. -template <template <class...> class Receiver> -using ExpandBasicComparableProfiles = - Receiver<ComparableNothrowMoveConstructibleProfile, - ComparableCopyConstructibleProfile, - ComparableNothrowMovableProfile, ComparableValueProfile>; - -// The basic profiles except that they are also all Hashable. -template <template <class...> class Receiver> -using ExpandBasicHashableProfiles = - Receiver<HashableNothrowMoveConstructibleProfile, - HashableCopyConstructibleProfile, HashableNothrowMovableProfile, - HashableValueProfile>; - -// The basic profiles except that they are also all DefaultConstructible. -template <template <class...> class Receiver> -using ExpandBasicDefaultConstructibleProfiles = - Receiver<DefaultConstructibleNothrowMoveConstructibleProfile, - DefaultConstructibleCopyConstructibleProfile, - DefaultConstructibleNothrowMovableProfile, - DefaultConstructibleValueProfile>; - -// The type profiles that we support in Abseil (all of the previous lists). -template <template <class...> class Receiver> -using ExpandSupportedProfiles = Receiver< - NothrowMoveConstructibleProfile, CopyConstructibleProfile, - NothrowMovableProfile, ValueProfile, - EquatableNothrowMoveConstructibleProfile, EquatableCopyConstructibleProfile, - EquatableNothrowMovableProfile, EquatableValueProfile, - ComparableNothrowMoveConstructibleProfile, - ComparableCopyConstructibleProfile, ComparableNothrowMovableProfile, - ComparableValueProfile, DefaultConstructibleNothrowMoveConstructibleProfile, - DefaultConstructibleCopyConstructibleProfile, - DefaultConstructibleNothrowMovableProfile, DefaultConstructibleValueProfile, - HashableNothrowMoveConstructibleProfile, HashableCopyConstructibleProfile, - HashableNothrowMovableProfile, HashableValueProfile>; - -// TODO(calabrese) Include types that have throwing move constructors, since in -// practice we still need to support them because of standard library types with -// (potentially) non-noexcept moves. - -} // namespace types_internal -ABSL_NAMESPACE_END -} // namespace absl - -#undef ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS - -#endif // ABSL_TYPES_INTERNAL_CONFORMANCE_ALIASES_H_ diff --git a/third_party/abseil_cpp/absl/types/internal/conformance_archetype.h b/third_party/abseil_cpp/absl/types/internal/conformance_archetype.h deleted file mode 100644 index 2349e0f72635..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/conformance_archetype.h +++ /dev/null @@ -1,978 +0,0 @@ -// Copyright 2019 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------- -// conformance_archetype.h -// ----------------------------------------------------------------------------- -// -// This file contains a facility for generating "archetypes" of out of -// "Conformance Profiles" (see "conformance_profiles.h" for more information -// about Conformance Profiles). An archetype is a type that aims to support the -// bare minimum requirements of a given Conformance Profile. For instance, an -// archetype that corresponds to an ImmutableProfile has exactly a nothrow -// move-constructor, a potentially-throwing copy constructor, a nothrow -// destructor, with all other special-member-functions deleted. These archetypes -// are useful for testing to make sure that templates are able to work with the -// kinds of types that they claim to support (i.e. that they do not accidentally -// under-constrain), -// -// The main type template in this file is the Archetype template, which takes -// a Conformance Profile as a template argument and its instantiations are a -// minimum-conforming model of that profile. - -#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_ARCHETYPE_H_ -#define ABSL_TYPES_INTERNAL_CONFORMANCE_ARCHETYPE_H_ - -#include <cstddef> -#include <functional> -#include <type_traits> -#include <utility> - -#include "absl/meta/type_traits.h" -#include "absl/types/internal/conformance_profile.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace types_internal { - -// A minimum-conforming implementation of a type with properties specified in -// `Prof`, where `Prof` is a valid Conformance Profile. -template <class Prof, class /*Enabler*/ = void> -class Archetype; - -// Given an Archetype, obtain the properties of the profile associated with that -// archetype. -template <class Archetype> -struct PropertiesOfArchetype; - -template <class Prof> -struct PropertiesOfArchetype<Archetype<Prof>> { - using type = PropertiesOfT<Prof>; -}; - -template <class Archetype> -using PropertiesOfArchetypeT = typename PropertiesOfArchetype<Archetype>::type; - -// A metafunction to determine if a type is an `Archetype`. -template <class T> -struct IsArchetype : std::false_type {}; - -template <class Prof> -struct IsArchetype<Archetype<Prof>> : std::true_type {}; - -// A constructor tag type used when creating an Archetype with internal state. -struct MakeArchetypeState {}; - -// Data stored within an archetype that is copied/compared/hashed when the -// corresponding operations are used. -using ArchetypeState = std::size_t; - -//////////////////////////////////////////////////////////////////////////////// -// This section of the file defines a chain of base classes for Archetype, // -// where each base defines a specific special member function with the // -// appropriate properties (deleted, noexcept(false), noexcept, or trivial). // -//////////////////////////////////////////////////////////////////////////////// - -// The bottom-most base, which contains the state and the default constructor. -template <default_constructible DefaultConstructibleValue> -struct ArchetypeStateBase { - static_assert(DefaultConstructibleValue == default_constructible::yes || - DefaultConstructibleValue == default_constructible::nothrow, - ""); - - ArchetypeStateBase() noexcept( - DefaultConstructibleValue == - default_constructible:: - nothrow) /*Vacuous archetype_state initialization*/ {} - explicit ArchetypeStateBase(MakeArchetypeState, ArchetypeState state) noexcept - : archetype_state(state) {} - - ArchetypeState archetype_state; -}; - -template <> -struct ArchetypeStateBase<default_constructible::maybe> { - explicit ArchetypeStateBase() = delete; - explicit ArchetypeStateBase(MakeArchetypeState, ArchetypeState state) noexcept - : archetype_state(state) {} - - ArchetypeState archetype_state; -}; - -template <> -struct ArchetypeStateBase<default_constructible::trivial> { - ArchetypeStateBase() = default; - explicit ArchetypeStateBase(MakeArchetypeState, ArchetypeState state) noexcept - : archetype_state(state) {} - - ArchetypeState archetype_state; -}; - -// The move-constructor base -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue> -struct ArchetypeMoveConstructor - : ArchetypeStateBase<DefaultConstructibleValue> { - static_assert(MoveConstructibleValue == move_constructible::yes || - MoveConstructibleValue == move_constructible::nothrow, - ""); - - explicit ArchetypeMoveConstructor(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeStateBase<DefaultConstructibleValue>(MakeArchetypeState(), - state) {} - - ArchetypeMoveConstructor() = default; - ArchetypeMoveConstructor(ArchetypeMoveConstructor&& other) noexcept( - MoveConstructibleValue == move_constructible::nothrow) - : ArchetypeStateBase<DefaultConstructibleValue>(MakeArchetypeState(), - other.archetype_state) {} - ArchetypeMoveConstructor(const ArchetypeMoveConstructor&) = default; - ArchetypeMoveConstructor& operator=(ArchetypeMoveConstructor&&) = default; - ArchetypeMoveConstructor& operator=(const ArchetypeMoveConstructor&) = - default; -}; - -template <default_constructible DefaultConstructibleValue> -struct ArchetypeMoveConstructor<DefaultConstructibleValue, - move_constructible::trivial> - : ArchetypeStateBase<DefaultConstructibleValue> { - explicit ArchetypeMoveConstructor(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeStateBase<DefaultConstructibleValue>(MakeArchetypeState(), - state) {} - - ArchetypeMoveConstructor() = default; -}; - -// The copy-constructor base -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue> -struct ArchetypeCopyConstructor - : ArchetypeMoveConstructor<DefaultConstructibleValue, - MoveConstructibleValue> { - static_assert(CopyConstructibleValue == copy_constructible::yes || - CopyConstructibleValue == copy_constructible::nothrow, - ""); - explicit ArchetypeCopyConstructor(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeMoveConstructor<DefaultConstructibleValue, - MoveConstructibleValue>(MakeArchetypeState(), - state) {} - - ArchetypeCopyConstructor() = default; - ArchetypeCopyConstructor(ArchetypeCopyConstructor&&) = default; - ArchetypeCopyConstructor(const ArchetypeCopyConstructor& other) noexcept( - CopyConstructibleValue == copy_constructible::nothrow) - : ArchetypeMoveConstructor<DefaultConstructibleValue, - MoveConstructibleValue>( - MakeArchetypeState(), other.archetype_state) {} - ArchetypeCopyConstructor& operator=(ArchetypeCopyConstructor&&) = default; - ArchetypeCopyConstructor& operator=(const ArchetypeCopyConstructor&) = - default; -}; - -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue> -struct ArchetypeCopyConstructor<DefaultConstructibleValue, - MoveConstructibleValue, - copy_constructible::maybe> - : ArchetypeMoveConstructor<DefaultConstructibleValue, - MoveConstructibleValue> { - explicit ArchetypeCopyConstructor(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeMoveConstructor<DefaultConstructibleValue, - MoveConstructibleValue>(MakeArchetypeState(), - state) {} - - ArchetypeCopyConstructor() = default; - ArchetypeCopyConstructor(ArchetypeCopyConstructor&&) = default; - ArchetypeCopyConstructor(const ArchetypeCopyConstructor&) = delete; - ArchetypeCopyConstructor& operator=(ArchetypeCopyConstructor&&) = default; - ArchetypeCopyConstructor& operator=(const ArchetypeCopyConstructor&) = - default; -}; - -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue> -struct ArchetypeCopyConstructor<DefaultConstructibleValue, - MoveConstructibleValue, - copy_constructible::trivial> - : ArchetypeMoveConstructor<DefaultConstructibleValue, - MoveConstructibleValue> { - explicit ArchetypeCopyConstructor(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeMoveConstructor<DefaultConstructibleValue, - MoveConstructibleValue>(MakeArchetypeState(), - state) {} - - ArchetypeCopyConstructor() = default; -}; - -// The move-assign base -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue, - move_assignable MoveAssignableValue> -struct ArchetypeMoveAssign - : ArchetypeCopyConstructor<DefaultConstructibleValue, - MoveConstructibleValue, CopyConstructibleValue> { - static_assert(MoveAssignableValue == move_assignable::yes || - MoveAssignableValue == move_assignable::nothrow, - ""); - explicit ArchetypeMoveAssign(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeCopyConstructor<DefaultConstructibleValue, - MoveConstructibleValue, - CopyConstructibleValue>(MakeArchetypeState(), - state) {} - - ArchetypeMoveAssign() = default; - ArchetypeMoveAssign(ArchetypeMoveAssign&&) = default; - ArchetypeMoveAssign(const ArchetypeMoveAssign&) = default; - ArchetypeMoveAssign& operator=(ArchetypeMoveAssign&& other) noexcept( - MoveAssignableValue == move_assignable::nothrow) { - this->archetype_state = other.archetype_state; - return *this; - } - - ArchetypeMoveAssign& operator=(const ArchetypeMoveAssign&) = default; -}; - -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue> -struct ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, move_assignable::trivial> - : ArchetypeCopyConstructor<DefaultConstructibleValue, - MoveConstructibleValue, CopyConstructibleValue> { - explicit ArchetypeMoveAssign(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeCopyConstructor<DefaultConstructibleValue, - MoveConstructibleValue, - CopyConstructibleValue>(MakeArchetypeState(), - state) {} - - ArchetypeMoveAssign() = default; -}; - -// The copy-assign base -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue, - move_assignable MoveAssignableValue, - copy_assignable CopyAssignableValue> -struct ArchetypeCopyAssign - : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue> { - static_assert(CopyAssignableValue == copy_assignable::yes || - CopyAssignableValue == copy_assignable::nothrow, - ""); - explicit ArchetypeCopyAssign(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue>( - MakeArchetypeState(), state) {} - - ArchetypeCopyAssign() = default; - ArchetypeCopyAssign(ArchetypeCopyAssign&&) = default; - ArchetypeCopyAssign(const ArchetypeCopyAssign&) = default; - ArchetypeCopyAssign& operator=(ArchetypeCopyAssign&&) = default; - - ArchetypeCopyAssign& operator=(const ArchetypeCopyAssign& other) noexcept( - CopyAssignableValue == copy_assignable::nothrow) { - this->archetype_state = other.archetype_state; - return *this; - } -}; - -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue, - move_assignable MoveAssignableValue> -struct ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue, - copy_assignable::maybe> - : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue> { - explicit ArchetypeCopyAssign(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue>( - MakeArchetypeState(), state) {} - - ArchetypeCopyAssign() = default; - ArchetypeCopyAssign(ArchetypeCopyAssign&&) = default; - ArchetypeCopyAssign(const ArchetypeCopyAssign&) = default; - ArchetypeCopyAssign& operator=(ArchetypeCopyAssign&&) = default; - ArchetypeCopyAssign& operator=(const ArchetypeCopyAssign&) = delete; -}; - -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue, - move_assignable MoveAssignableValue> -struct ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue, - copy_assignable::trivial> - : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue> { - explicit ArchetypeCopyAssign(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue>( - MakeArchetypeState(), state) {} - - ArchetypeCopyAssign() = default; -}; - -// The destructor base -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue, - move_assignable MoveAssignableValue, - copy_assignable CopyAssignableValue, destructible DestructibleValue> -struct ArchetypeDestructor - : ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue, - CopyAssignableValue> { - static_assert(DestructibleValue == destructible::yes || - DestructibleValue == destructible::nothrow, - ""); - - explicit ArchetypeDestructor(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue, - CopyAssignableValue>(MakeArchetypeState(), state) {} - - ArchetypeDestructor() = default; - ArchetypeDestructor(ArchetypeDestructor&&) = default; - ArchetypeDestructor(const ArchetypeDestructor&) = default; - ArchetypeDestructor& operator=(ArchetypeDestructor&&) = default; - ArchetypeDestructor& operator=(const ArchetypeDestructor&) = default; - ~ArchetypeDestructor() noexcept(DestructibleValue == destructible::nothrow) {} -}; - -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue, - move_assignable MoveAssignableValue, - copy_assignable CopyAssignableValue> -struct ArchetypeDestructor<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue, - CopyAssignableValue, destructible::trivial> - : ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue, - CopyAssignableValue> { - explicit ArchetypeDestructor(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue, - CopyAssignableValue>(MakeArchetypeState(), state) {} - - ArchetypeDestructor() = default; -}; - -// An alias to the top of the chain of bases for special-member functions. -// NOTE: move_constructible::maybe, move_assignable::maybe, and -// destructible::maybe are handled in the top-level type by way of SFINAE. -// Because of this, we never instantiate the base classes with -// move_constructible::maybe, move_assignable::maybe, or destructible::maybe so -// that we minimize the number of different possible type-template -// instantiations. -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue, - move_assignable MoveAssignableValue, - copy_assignable CopyAssignableValue, destructible DestructibleValue> -using ArchetypeSpecialMembersBase = ArchetypeDestructor< - DefaultConstructibleValue, - MoveConstructibleValue != move_constructible::maybe - ? MoveConstructibleValue - : move_constructible::nothrow, - CopyConstructibleValue, - MoveAssignableValue != move_assignable::maybe ? MoveAssignableValue - : move_assignable::nothrow, - CopyAssignableValue, - DestructibleValue != destructible::maybe ? DestructibleValue - : destructible::nothrow>; - -// A function that is used to create an archetype with some associated state. -template <class Arch> -Arch MakeArchetype(ArchetypeState state) noexcept { - static_assert(IsArchetype<Arch>::value, - "The explicit template argument to MakeArchetype is required " - "to be an Archetype."); - return Arch(MakeArchetypeState(), state); -} - -// This is used to conditionally delete "copy" and "move" constructors in a way -// that is consistent with what the ConformanceProfile requires and that also -// strictly enforces the arguments to the copy/move to not come from implicit -// conversions when dealing with the Archetype. -template <class Prof, class T> -constexpr bool ShouldDeleteConstructor() { - return !((PropertiesOfT<Prof>::move_constructible_support != - move_constructible::maybe && - std::is_same<T, Archetype<Prof>>::value) || - (PropertiesOfT<Prof>::copy_constructible_support != - copy_constructible::maybe && - (std::is_same<T, const Archetype<Prof>&>::value || - std::is_same<T, Archetype<Prof>&>::value || - std::is_same<T, const Archetype<Prof>>::value))); -} - -// This is used to conditionally delete "copy" and "move" assigns in a way -// that is consistent with what the ConformanceProfile requires and that also -// strictly enforces the arguments to the copy/move to not come from implicit -// conversions when dealing with the Archetype. -template <class Prof, class T> -constexpr bool ShouldDeleteAssign() { - return !( - (PropertiesOfT<Prof>::move_assignable_support != move_assignable::maybe && - std::is_same<T, Archetype<Prof>>::value) || - (PropertiesOfT<Prof>::copy_assignable_support != copy_assignable::maybe && - (std::is_same<T, const Archetype<Prof>&>::value || - std::is_same<T, Archetype<Prof>&>::value || - std::is_same<T, const Archetype<Prof>>::value))); -} - -// TODO(calabrese) Inherit from a chain of secondary bases to pull in the -// associated functions of other concepts. -template <class Prof, class Enabler> -class Archetype : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support> { - static_assert(std::is_same<Enabler, void>::value, - "An explicit type must not be passed as the second template " - "argument to 'Archetype`."); - - // The cases mentioned in these static_asserts are expected to be handled in - // the partial template specializations of Archetype that follow this - // definition. - static_assert(PropertiesOfT<Prof>::destructible_support != - destructible::maybe, - ""); - static_assert(PropertiesOfT<Prof>::move_constructible_support != - move_constructible::maybe || - PropertiesOfT<Prof>::copy_constructible_support == - copy_constructible::maybe, - ""); - static_assert(PropertiesOfT<Prof>::move_assignable_support != - move_assignable::maybe || - PropertiesOfT<Prof>::copy_assignable_support == - copy_assignable::maybe, - ""); - - public: - Archetype() = default; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteConstructor<Prof, T>()>::type* = nullptr> - Archetype(T&&) = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteAssign<Prof, T>()>::type* = nullptr> - Archetype& operator=(T&&) = delete; - - using ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>::archetype_state; - - private: - explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(), - state) {} - - friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept; -}; - -template <class Prof> -class Archetype<Prof, typename std::enable_if< - PropertiesOfT<Prof>::move_constructible_support != - move_constructible::maybe && - PropertiesOfT<Prof>::move_assignable_support == - move_assignable::maybe && - PropertiesOfT<Prof>::destructible_support != - destructible::maybe>::type> - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support> { - public: - Archetype() = default; - Archetype(Archetype&&) = default; - Archetype(const Archetype&) = default; - Archetype& operator=(Archetype&&) = delete; - Archetype& operator=(const Archetype&) = default; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteConstructor<Prof, T>()>::type* = nullptr> - Archetype(T&&) = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteAssign<Prof, T>()>::type* = nullptr> - Archetype& operator=(T&&) = delete; - - using ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>::archetype_state; - - private: - explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(), - state) {} - - friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept; -}; - -template <class Prof> -class Archetype<Prof, typename std::enable_if< - PropertiesOfT<Prof>::move_constructible_support == - move_constructible::maybe && - PropertiesOfT<Prof>::move_assignable_support == - move_assignable::maybe && - PropertiesOfT<Prof>::destructible_support != - destructible::maybe>::type> - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support> { - public: - Archetype() = default; - Archetype(Archetype&&) = delete; - Archetype(const Archetype&) = default; - Archetype& operator=(Archetype&&) = delete; - Archetype& operator=(const Archetype&) = default; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteConstructor<Prof, T>()>::type* = nullptr> - Archetype(T&&) = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteAssign<Prof, T>()>::type* = nullptr> - Archetype& operator=(T&&) = delete; - - using ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>::archetype_state; - - private: - explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(), - state) {} - - friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept; -}; - -template <class Prof> -class Archetype<Prof, typename std::enable_if< - PropertiesOfT<Prof>::move_constructible_support == - move_constructible::maybe && - PropertiesOfT<Prof>::move_assignable_support != - move_assignable::maybe && - PropertiesOfT<Prof>::destructible_support != - destructible::maybe>::type> - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support> { - public: - Archetype() = default; - Archetype(Archetype&&) = delete; - Archetype(const Archetype&) = default; - Archetype& operator=(Archetype&&) = default; - Archetype& operator=(const Archetype&) = default; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteConstructor<Prof, T>()>::type* = nullptr> - Archetype(T&&) = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteAssign<Prof, T>()>::type* = nullptr> - Archetype& operator=(T&&) = delete; - - using ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>::archetype_state; - - private: - explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(), - state) {} - - friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept; -}; - -template <class Prof> -class Archetype<Prof, typename std::enable_if< - PropertiesOfT<Prof>::move_constructible_support != - move_constructible::maybe && - PropertiesOfT<Prof>::move_assignable_support == - move_assignable::maybe && - PropertiesOfT<Prof>::destructible_support == - destructible::maybe>::type> - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support> { - public: - Archetype() = default; - Archetype(Archetype&&) = default; - Archetype(const Archetype&) = default; - Archetype& operator=(Archetype&&) = delete; - Archetype& operator=(const Archetype&) = default; - ~Archetype() = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteConstructor<Prof, T>()>::type* = nullptr> - Archetype(T&&) = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteAssign<Prof, T>()>::type* = nullptr> - Archetype& operator=(T&&) = delete; - - using ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>::archetype_state; - - private: - explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(), - state) {} - - friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept; -}; - -template <class Prof> -class Archetype<Prof, typename std::enable_if< - PropertiesOfT<Prof>::move_constructible_support == - move_constructible::maybe && - PropertiesOfT<Prof>::move_assignable_support == - move_assignable::maybe && - PropertiesOfT<Prof>::destructible_support == - destructible::maybe>::type> - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support> { - public: - Archetype() = default; - Archetype(Archetype&&) = delete; - Archetype(const Archetype&) = default; - Archetype& operator=(Archetype&&) = delete; - Archetype& operator=(const Archetype&) = default; - ~Archetype() = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteConstructor<Prof, T>()>::type* = nullptr> - Archetype(T&&) = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteAssign<Prof, T>()>::type* = nullptr> - Archetype& operator=(T&&) = delete; - - using ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>::archetype_state; - - private: - explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(), - state) {} - - friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept; -}; - -template <class Prof> -class Archetype<Prof, typename std::enable_if< - PropertiesOfT<Prof>::move_constructible_support == - move_constructible::maybe && - PropertiesOfT<Prof>::move_assignable_support != - move_assignable::maybe && - PropertiesOfT<Prof>::destructible_support == - destructible::maybe>::type> - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support> { - public: - Archetype() = default; - Archetype(Archetype&&) = delete; - Archetype(const Archetype&) = default; - Archetype& operator=(Archetype&&) = default; - Archetype& operator=(const Archetype&) = default; - ~Archetype() = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteConstructor<Prof, T>()>::type* = nullptr> - Archetype(T&&) = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteAssign<Prof, T>()>::type* = nullptr> - Archetype& operator=(T&&) = delete; - - using ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>::archetype_state; - - private: - explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(), - state) {} - - friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept; -}; - -// Explicitly deleted swap for Archetype if the profile does not require swap. -// It is important to delete it rather than simply leave it out so that the -// "using std::swap;" idiom will result in this deleted overload being picked. -template <class Prof, - absl::enable_if_t<!PropertiesOfT<Prof>::is_swappable, int> = 0> -void swap(Archetype<Prof>&, Archetype<Prof>&) = delete; // NOLINT - -// A conditionally-noexcept swap implementation for Archetype when the profile -// supports swap. -template <class Prof, - absl::enable_if_t<PropertiesOfT<Prof>::is_swappable, int> = 0> -void swap(Archetype<Prof>& lhs, Archetype<Prof>& rhs) // NOLINT - noexcept(PropertiesOfT<Prof>::swappable_support != swappable::yes) { - std::swap(lhs.archetype_state, rhs.archetype_state); -} - -// A convertible-to-bool type that is used as the return type of comparison -// operators since the standard doesn't always require exactly bool. -struct NothrowBool { - explicit NothrowBool() = delete; - ~NothrowBool() = default; - - // TODO(calabrese) Delete the copy constructor in C++17 mode since guaranteed - // elision makes it not required when returning from a function. - // NothrowBool(NothrowBool const&) = delete; - - NothrowBool& operator=(NothrowBool const&) = delete; - - explicit operator bool() const noexcept { return value; } - - static NothrowBool make(bool const value) noexcept { - return NothrowBool(value); - } - - private: - explicit NothrowBool(bool const value) noexcept : value(value) {} - - bool value; -}; - -// A convertible-to-bool type that is used as the return type of comparison -// operators since the standard doesn't always require exactly bool. -// Note: ExceptionalBool has a conversion operator that is not noexcept, so -// that even when a comparison operator is noexcept, that operation may still -// potentially throw when converted to bool. -struct ExceptionalBool { - explicit ExceptionalBool() = delete; - ~ExceptionalBool() = default; - - // TODO(calabrese) Delete the copy constructor in C++17 mode since guaranteed - // elision makes it not required when returning from a function. - // ExceptionalBool(ExceptionalBool const&) = delete; - - ExceptionalBool& operator=(ExceptionalBool const&) = delete; - - explicit operator bool() const { return value; } // NOLINT - - static ExceptionalBool make(bool const value) noexcept { - return ExceptionalBool(value); - } - - private: - explicit ExceptionalBool(bool const value) noexcept : value(value) {} - - bool value; -}; - -// The following macro is only used as a helper in this file to stamp out -// comparison operator definitions. It is undefined after usage. -// -// NOTE: Non-nothrow operators throw via their result's conversion to bool even -// though the operation itself is noexcept. -#define ABSL_TYPES_INTERNAL_OP(enum_name, op) \ - template <class Prof> \ - absl::enable_if_t<!PropertiesOfT<Prof>::is_##enum_name, bool> operator op( \ - const Archetype<Prof>&, const Archetype<Prof>&) = delete; \ - \ - template <class Prof> \ - typename absl::enable_if_t< \ - PropertiesOfT<Prof>::is_##enum_name, \ - std::conditional<PropertiesOfT<Prof>::enum_name##_support == \ - enum_name::nothrow, \ - NothrowBool, ExceptionalBool>>::type \ - operator op(const Archetype<Prof>& lhs, \ - const Archetype<Prof>& rhs) noexcept { \ - return absl::conditional_t< \ - PropertiesOfT<Prof>::enum_name##_support == enum_name::nothrow, \ - NothrowBool, ExceptionalBool>::make(lhs.archetype_state op \ - rhs.archetype_state); \ - } - -ABSL_TYPES_INTERNAL_OP(equality_comparable, ==); -ABSL_TYPES_INTERNAL_OP(inequality_comparable, !=); -ABSL_TYPES_INTERNAL_OP(less_than_comparable, <); -ABSL_TYPES_INTERNAL_OP(less_equal_comparable, <=); -ABSL_TYPES_INTERNAL_OP(greater_equal_comparable, >=); -ABSL_TYPES_INTERNAL_OP(greater_than_comparable, >); - -#undef ABSL_TYPES_INTERNAL_OP - -// Base class for std::hash specializations when an Archetype doesn't support -// hashing. -struct PoisonedHash { - PoisonedHash() = delete; - PoisonedHash(const PoisonedHash&) = delete; - PoisonedHash& operator=(const PoisonedHash&) = delete; -}; - -// Base class for std::hash specializations when an Archetype supports hashing. -template <class Prof> -struct EnabledHash { - using argument_type = Archetype<Prof>; - using result_type = std::size_t; - result_type operator()(const argument_type& arg) const { - return std::hash<ArchetypeState>()(arg.archetype_state); - } -}; - -} // namespace types_internal -ABSL_NAMESPACE_END -} // namespace absl - -namespace std { - -template <class Prof> // NOLINT -struct hash<::absl::types_internal::Archetype<Prof>> - : conditional<::absl::types_internal::PropertiesOfT<Prof>::is_hashable, - ::absl::types_internal::EnabledHash<Prof>, - ::absl::types_internal::PoisonedHash>::type {}; - -} // namespace std - -#endif // ABSL_TYPES_INTERNAL_CONFORMANCE_ARCHETYPE_H_ diff --git a/third_party/abseil_cpp/absl/types/internal/conformance_profile.h b/third_party/abseil_cpp/absl/types/internal/conformance_profile.h deleted file mode 100644 index cf64ff4fcd1e..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/conformance_profile.h +++ /dev/null @@ -1,931 +0,0 @@ -// Copyright 2019 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------- -// conformance_profiles.h -// ----------------------------------------------------------------------------- -// -// This file contains templates for representing "Regularity Profiles" and -// concisely-named versions of commonly used Regularity Profiles. -// -// A Regularity Profile is a compile-time description of the types of operations -// that a given type supports, along with properties of those operations when -// they do exist. For instance, a Regularity Profile may describe a type that -// has a move-constructor that is noexcept and a copy constructor that is not -// noexcept. This description can then be examined and passed around to other -// templates for the purposes of asserting expectations on user-defined types -// via a series trait checks, or for determining what kinds of run-time tests -// are able to be performed. -// -// Regularity Profiles are also used when creating "archetypes," which are -// minimum-conforming types that meet all of the requirements of a given -// Regularity Profile. For more information regarding archetypes, see -// "conformance_archetypes.h". - -#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_PROFILE_H_ -#define ABSL_TYPES_INTERNAL_CONFORMANCE_PROFILE_H_ - -#include <set> -#include <type_traits> -#include <utility> -#include <vector> - -#include "gtest/gtest.h" -#include "absl/algorithm/container.h" -#include "absl/meta/type_traits.h" -#include "absl/strings/ascii.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/string_view.h" -#include "absl/types/internal/conformance_testing_helpers.h" -#include "absl/utility/utility.h" - -// TODO(calabrese) Add support for extending profiles. - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace types_internal { - -// Converts an enum to its underlying integral value. -template <typename Enum> -constexpr absl::underlying_type_t<Enum> UnderlyingValue(Enum value) { - return static_cast<absl::underlying_type_t<Enum>>(value); -} - -// A tag type used in place of a matcher when checking that an assertion result -// does not actually contain any errors. -struct NoError {}; - -// ----------------------------------------------------------------------------- -// ConformanceErrors -// ----------------------------------------------------------------------------- -class ConformanceErrors { - public: - // Setup the error reporting mechanism by seeding it with the name of the type - // that is being tested. - explicit ConformanceErrors(std::string type_name) - : assertion_result_(false), type_name_(std::move(type_name)) { - assertion_result_ << "\n\n" - "Assuming the following type alias:\n" - "\n" - " using _T = " - << type_name_ << ";\n\n"; - outputDivider(); - } - - // Adds the test name to the list of successfully run tests iff it was not - // previously reported as failing. This behavior is useful for tests that - // have multiple parts, where failures and successes are reported individually - // with the same test name. - void addTestSuccess(absl::string_view test_name) { - auto normalized_test_name = absl::AsciiStrToLower(test_name); - - // If the test is already reported as failing, do not add it to the list of - // successes. - if (test_failures_.find(normalized_test_name) == test_failures_.end()) { - test_successes_.insert(std::move(normalized_test_name)); - } - } - - // Streams a single error description into the internal buffer (a visual - // divider is automatically inserted after the error so that multiple errors - // are visibly distinct). - // - // This function increases the error count by 1. - // - // TODO(calabrese) Determine desired behavior when if this function throws. - template <class... P> - void addTestFailure(absl::string_view test_name, const P&... args) { - // Output a message related to the test failure. - assertion_result_ << "\n\n" - "Failed test: " - << test_name << "\n\n"; - addTestFailureImpl(args...); - assertion_result_ << "\n\n"; - outputDivider(); - - auto normalized_test_name = absl::AsciiStrToLower(test_name); - - // If previous parts of this test succeeded, remove it from that set. - test_successes_.erase(normalized_test_name); - - // Add the test name to the list of failed tests. - test_failures_.insert(std::move(normalized_test_name)); - - has_error_ = true; - } - - // Convert this object into a testing::AssertionResult instance such that it - // can be used with gtest. - ::testing::AssertionResult assertionResult() const { - return has_error_ ? assertion_result_ : ::testing::AssertionSuccess(); - } - - // Convert this object into a testing::AssertionResult instance such that it - // can be used with gtest. This overload expects errors, using the specified - // matcher. - ::testing::AssertionResult expectFailedTests( - const std::set<std::string>& test_names) const { - // Since we are expecting nonconformance, output an error message when the - // type actually conformed to the specified profile. - if (!has_error_) { - return ::testing::AssertionFailure() - << "Unexpected conformance of type:\n" - " " - << type_name_ << "\n\n"; - } - - // Get a list of all expected failures that did not actually fail - // (or that were not run). - std::vector<std::string> nonfailing_tests; - absl::c_set_difference(test_names, test_failures_, - std::back_inserter(nonfailing_tests)); - - // Get a list of all "expected failures" that were never actually run. - std::vector<std::string> unrun_tests; - absl::c_set_difference(nonfailing_tests, test_successes_, - std::back_inserter(unrun_tests)); - - // Report when the user specified tests that were not run. - if (!unrun_tests.empty()) { - const bool tests_were_run = - !(test_failures_.empty() && test_successes_.empty()); - - // Prepare an assertion result used in the case that tests pass that were - // expected to fail. - ::testing::AssertionResult result = ::testing::AssertionFailure(); - result << "When testing type:\n " << type_name_ - << "\n\nThe following tests were expected to fail but were not " - "run"; - - if (tests_were_run) result << " (was the test name spelled correctly?)"; - - result << ":\n\n"; - - // List all of the tests that unexpectedly passed. - for (const auto& test_name : unrun_tests) { - result << " " << test_name << "\n"; - } - - if (!tests_were_run) result << "\nNo tests were run."; - - if (!test_failures_.empty()) { - // List test failures - result << "\nThe tests that were run and failed are:\n\n"; - for (const auto& test_name : test_failures_) { - result << " " << test_name << "\n"; - } - } - - if (!test_successes_.empty()) { - // List test successes - result << "\nThe tests that were run and succeeded are:\n\n"; - for (const auto& test_name : test_successes_) { - result << " " << test_name << "\n"; - } - } - - return result; - } - - // If some tests passed when they were expected to fail, alert the caller. - if (nonfailing_tests.empty()) return ::testing::AssertionSuccess(); - - // Prepare an assertion result used in the case that tests pass that were - // expected to fail. - ::testing::AssertionResult unexpected_successes = - ::testing::AssertionFailure(); - unexpected_successes << "When testing type:\n " << type_name_ - << "\n\nThe following tests passed when they were " - "expected to fail:\n\n"; - - // List all of the tests that unexpectedly passed. - for (const auto& test_name : nonfailing_tests) { - unexpected_successes << " " << test_name << "\n"; - } - - return unexpected_successes; - } - - private: - void outputDivider() { - assertion_result_ << "========================================"; - } - - void addTestFailureImpl() {} - - template <class H, class... T> - void addTestFailureImpl(const H& head, const T&... tail) { - assertion_result_ << head; - addTestFailureImpl(tail...); - } - - ::testing::AssertionResult assertion_result_; - std::set<std::string> test_failures_; - std::set<std::string> test_successes_; - std::string type_name_; - bool has_error_ = false; -}; - -template <class T, class /*Enabler*/ = void> -struct PropertiesOfImpl {}; - -template <class T> -struct PropertiesOfImpl<T, absl::void_t<typename T::properties>> { - using type = typename T::properties; -}; - -template <class T> -struct PropertiesOfImpl<T, absl::void_t<typename T::profile_alias_of>> { - using type = typename PropertiesOfImpl<typename T::profile_alias_of>::type; -}; - -template <class T> -struct PropertiesOf : PropertiesOfImpl<T> {}; - -template <class T> -using PropertiesOfT = typename PropertiesOf<T>::type; - -// NOTE: These enums use this naming convention to be consistent with the -// standard trait names, which is useful since it allows us to match up each -// enum name with a corresponding trait name in macro definitions. - -// An enum that describes the various expectations on an operations existence. -enum class function_support { maybe, yes, nothrow, trivial }; - -constexpr const char* PessimisticPropertyDescription(function_support v) { - return v == function_support::maybe - ? "no" - : v == function_support::yes - ? "yes, potentially throwing" - : v == function_support::nothrow ? "yes, nothrow" - : "yes, trivial"; -} - -// Return a string that describes the kind of property support that was -// expected. -inline std::string ExpectedFunctionKindList(function_support min, - function_support max) { - if (min == max) { - std::string result = - absl::StrCat("Expected:\n ", - PessimisticPropertyDescription( - static_cast<function_support>(UnderlyingValue(min))), - "\n"); - return result; - } - - std::string result = "Expected one of:\n"; - for (auto curr_support = UnderlyingValue(min); - curr_support <= UnderlyingValue(max); ++curr_support) { - absl::StrAppend(&result, " ", - PessimisticPropertyDescription( - static_cast<function_support>(curr_support)), - "\n"); - } - - return result; -} - -template <class Enum> -void ExpectModelOfImpl(ConformanceErrors* errors, Enum min_support, - Enum max_support, Enum kind) { - const auto kind_value = UnderlyingValue(kind); - const auto min_support_value = UnderlyingValue(min_support); - const auto max_support_value = UnderlyingValue(max_support); - - if (!(kind_value >= min_support_value && kind_value <= max_support_value)) { - errors->addTestFailure( - PropertyName(kind), "**Failed property expectation**\n\n", - ExpectedFunctionKindList( - static_cast<function_support>(min_support_value), - static_cast<function_support>(max_support_value)), - '\n', "Actual:\n ", - PessimisticPropertyDescription( - static_cast<function_support>(kind_value))); - } else { - errors->addTestSuccess(PropertyName(kind)); - } -} - -#define ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM(description, name) \ - enum class name { maybe, yes, nothrow, trivial }; \ - \ - constexpr const char* PropertyName(name v) { return description; } \ - static_assert(true, "") // Force a semicolon when using this macro. - -ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for default construction", - default_constructible); -ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for move construction", - move_constructible); -ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for copy construction", - copy_constructible); -ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for move assignment", - move_assignable); -ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for copy assignment", - copy_assignable); -ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for destruction", - destructible); - -#undef ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM - -#define ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM(description, name) \ - enum class name { maybe, yes, nothrow }; \ - \ - constexpr const char* PropertyName(name v) { return description; } \ - static_assert(true, "") // Force a semicolon when using this macro. - -ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for ==", equality_comparable); -ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for !=", inequality_comparable); -ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for <", less_than_comparable); -ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for <=", less_equal_comparable); -ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for >=", - greater_equal_comparable); -ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for >", greater_than_comparable); - -ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for swap", swappable); - -#undef ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM - -enum class hashable { maybe, yes }; - -constexpr const char* PropertyName(hashable v) { - return "support for std::hash"; -} - -template <class T> -using AlwaysFalse = std::false_type; - -#define ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(name, property) \ - template <class T> \ - constexpr property property##_support_of() { \ - return std::is_##property<T>::value \ - ? std::is_nothrow_##property<T>::value \ - ? absl::is_trivially_##property<T>::value \ - ? property::trivial \ - : property::nothrow \ - : property::yes \ - : property::maybe; \ - } \ - \ - template <class T, class MinProf, class MaxProf> \ - void ExpectModelOf##name(ConformanceErrors* errors) { \ - (ExpectModelOfImpl)(errors, PropertiesOfT<MinProf>::property##_support, \ - PropertiesOfT<MaxProf>::property##_support, \ - property##_support_of<T>()); \ - } - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(DefaultConstructible, - default_constructible); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(MoveConstructible, - move_constructible); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(CopyConstructible, - copy_constructible); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(MoveAssignable, - move_assignable); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(CopyAssignable, - copy_assignable); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(Destructible, destructible); - -#undef ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER - -void BoolFunction(bool) noexcept; - -//////////////////////////////////////////////////////////////////////////////// -// -// A metafunction for checking if an operation exists through SFINAE. -// -// `T` is the type to test and Op is an alias containing the expression to test. -template <class T, template <class...> class Op, class = void> -struct IsOpableImpl : std::false_type {}; - -template <class T, template <class...> class Op> -struct IsOpableImpl<T, Op, absl::void_t<Op<T>>> : std::true_type {}; - -template <template <class...> class Op> -struct IsOpable { - template <class T> - using apply = typename IsOpableImpl<T, Op>::type; -}; -// -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -// -// A metafunction for checking if an operation exists and is also noexcept -// through SFINAE and the noexcept operator. -/// -// `T` is the type to test and Op is an alias containing the expression to test. -template <class T, template <class...> class Op, class = void> -struct IsNothrowOpableImpl : std::false_type {}; - -template <class T, template <class...> class Op> -struct IsNothrowOpableImpl<T, Op, absl::enable_if_t<Op<T>::value>> - : std::true_type {}; - -template <template <class...> class Op> -struct IsNothrowOpable { - template <class T> - using apply = typename IsNothrowOpableImpl<T, Op>::type; -}; -// -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -// -// A macro that produces the necessary function for reporting what kind of -// support a specific comparison operation has and a function for reporting an -// error if a given type's support for that operation does not meet the expected -// requirements. -#define ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(name, property, op) \ - template <class T, \ - class Result = std::integral_constant< \ - bool, noexcept((BoolFunction)(std::declval<const T&>() op \ - std::declval<const T&>()))>> \ - using name = Result; \ - \ - template <class T> \ - constexpr property property##_support_of() { \ - return IsOpable<name>::apply<T>::value \ - ? IsNothrowOpable<name>::apply<T>::value ? property::nothrow \ - : property::yes \ - : property::maybe; \ - } \ - \ - template <class T, class MinProf, class MaxProf> \ - void ExpectModelOf##name(ConformanceErrors* errors) { \ - (ExpectModelOfImpl)(errors, PropertiesOfT<MinProf>::property##_support, \ - PropertiesOfT<MaxProf>::property##_support, \ - property##_support_of<T>()); \ - } -// -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -// -// Generate the necessary support-checking and error reporting functions for -// each of the comparison operators. -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(EqualityComparable, - equality_comparable, ==); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(InequalityComparable, - inequality_comparable, !=); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(LessThanComparable, - less_than_comparable, <); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(LessEqualComparable, - less_equal_comparable, <=); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(GreaterEqualComparable, - greater_equal_comparable, >=); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(GreaterThanComparable, - greater_than_comparable, >); - -#undef ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON -// -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -// -// The necessary support-checking and error-reporting functions for swap. -template <class T> -constexpr swappable swappable_support_of() { - return type_traits_internal::IsSwappable<T>::value - ? type_traits_internal::IsNothrowSwappable<T>::value - ? swappable::nothrow - : swappable::yes - : swappable::maybe; -} - -template <class T, class MinProf, class MaxProf> -void ExpectModelOfSwappable(ConformanceErrors* errors) { - (ExpectModelOfImpl)(errors, PropertiesOfT<MinProf>::swappable_support, - PropertiesOfT<MaxProf>::swappable_support, - swappable_support_of<T>()); -} -// -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -// -// The necessary support-checking and error-reporting functions for std::hash. -template <class T> -constexpr hashable hashable_support_of() { - return type_traits_internal::IsHashable<T>::value ? hashable::yes - : hashable::maybe; -} - -template <class T, class MinProf, class MaxProf> -void ExpectModelOfHashable(ConformanceErrors* errors) { - (ExpectModelOfImpl)(errors, PropertiesOfT<MinProf>::hashable_support, - PropertiesOfT<MaxProf>::hashable_support, - hashable_support_of<T>()); -} -// -//////////////////////////////////////////////////////////////////////////////// - -template < - default_constructible DefaultConstructibleValue = - default_constructible::maybe, - move_constructible MoveConstructibleValue = move_constructible::maybe, - copy_constructible CopyConstructibleValue = copy_constructible::maybe, - move_assignable MoveAssignableValue = move_assignable::maybe, - copy_assignable CopyAssignableValue = copy_assignable::maybe, - destructible DestructibleValue = destructible::maybe, - equality_comparable EqualityComparableValue = equality_comparable::maybe, - inequality_comparable InequalityComparableValue = - inequality_comparable::maybe, - less_than_comparable LessThanComparableValue = less_than_comparable::maybe, - less_equal_comparable LessEqualComparableValue = - less_equal_comparable::maybe, - greater_equal_comparable GreaterEqualComparableValue = - greater_equal_comparable::maybe, - greater_than_comparable GreaterThanComparableValue = - greater_than_comparable::maybe, - swappable SwappableValue = swappable::maybe, - hashable HashableValue = hashable::maybe> -struct ConformanceProfile { - using properties = ConformanceProfile; - - static constexpr default_constructible - default_constructible_support = // NOLINT - DefaultConstructibleValue; - - static constexpr move_constructible move_constructible_support = // NOLINT - MoveConstructibleValue; - - static constexpr copy_constructible copy_constructible_support = // NOLINT - CopyConstructibleValue; - - static constexpr move_assignable move_assignable_support = // NOLINT - MoveAssignableValue; - - static constexpr copy_assignable copy_assignable_support = // NOLINT - CopyAssignableValue; - - static constexpr destructible destructible_support = // NOLINT - DestructibleValue; - - static constexpr equality_comparable equality_comparable_support = // NOLINT - EqualityComparableValue; - - static constexpr inequality_comparable - inequality_comparable_support = // NOLINT - InequalityComparableValue; - - static constexpr less_than_comparable - less_than_comparable_support = // NOLINT - LessThanComparableValue; - - static constexpr less_equal_comparable - less_equal_comparable_support = // NOLINT - LessEqualComparableValue; - - static constexpr greater_equal_comparable - greater_equal_comparable_support = // NOLINT - GreaterEqualComparableValue; - - static constexpr greater_than_comparable - greater_than_comparable_support = // NOLINT - GreaterThanComparableValue; - - static constexpr swappable swappable_support = SwappableValue; // NOLINT - - static constexpr hashable hashable_support = HashableValue; // NOLINT - - static constexpr bool is_default_constructible = // NOLINT - DefaultConstructibleValue != default_constructible::maybe; - - static constexpr bool is_move_constructible = // NOLINT - MoveConstructibleValue != move_constructible::maybe; - - static constexpr bool is_copy_constructible = // NOLINT - CopyConstructibleValue != copy_constructible::maybe; - - static constexpr bool is_move_assignable = // NOLINT - MoveAssignableValue != move_assignable::maybe; - - static constexpr bool is_copy_assignable = // NOLINT - CopyAssignableValue != copy_assignable::maybe; - - static constexpr bool is_destructible = // NOLINT - DestructibleValue != destructible::maybe; - - static constexpr bool is_equality_comparable = // NOLINT - EqualityComparableValue != equality_comparable::maybe; - - static constexpr bool is_inequality_comparable = // NOLINT - InequalityComparableValue != inequality_comparable::maybe; - - static constexpr bool is_less_than_comparable = // NOLINT - LessThanComparableValue != less_than_comparable::maybe; - - static constexpr bool is_less_equal_comparable = // NOLINT - LessEqualComparableValue != less_equal_comparable::maybe; - - static constexpr bool is_greater_equal_comparable = // NOLINT - GreaterEqualComparableValue != greater_equal_comparable::maybe; - - static constexpr bool is_greater_than_comparable = // NOLINT - GreaterThanComparableValue != greater_than_comparable::maybe; - - static constexpr bool is_swappable = // NOLINT - SwappableValue != swappable::maybe; - - static constexpr bool is_hashable = // NOLINT - HashableValue != hashable::maybe; -}; - -//////////////////////////////////////////////////////////////////////////////// -// -// Compliant SFINAE-friendliness is not always present on the standard library -// implementations that we support. This helper-struct (and associated enum) is -// used as a means to conditionally check the hashability support of a type. -enum class CheckHashability { no, yes }; - -template <class T, CheckHashability ShouldCheckHashability> -struct conservative_hashable_support_of; - -template <class T> -struct conservative_hashable_support_of<T, CheckHashability::no> { - static constexpr hashable Invoke() { return hashable::maybe; } -}; - -template <class T> -struct conservative_hashable_support_of<T, CheckHashability::yes> { - static constexpr hashable Invoke() { return hashable_support_of<T>(); } -}; -// -//////////////////////////////////////////////////////////////////////////////// - -// The ConformanceProfile that is expected based on introspection into the type -// by way of trait checks. -template <class T, CheckHashability ShouldCheckHashability> -struct SyntacticConformanceProfileOf { - using properties = ConformanceProfile< - default_constructible_support_of<T>(), move_constructible_support_of<T>(), - copy_constructible_support_of<T>(), move_assignable_support_of<T>(), - copy_assignable_support_of<T>(), destructible_support_of<T>(), - equality_comparable_support_of<T>(), - inequality_comparable_support_of<T>(), - less_than_comparable_support_of<T>(), - less_equal_comparable_support_of<T>(), - greater_equal_comparable_support_of<T>(), - greater_than_comparable_support_of<T>(), swappable_support_of<T>(), - conservative_hashable_support_of<T, ShouldCheckHashability>::Invoke()>; -}; - -#define ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL(type, name) \ - template <default_constructible DefaultConstructibleValue, \ - move_constructible MoveConstructibleValue, \ - copy_constructible CopyConstructibleValue, \ - move_assignable MoveAssignableValue, \ - copy_assignable CopyAssignableValue, \ - destructible DestructibleValue, \ - equality_comparable EqualityComparableValue, \ - inequality_comparable InequalityComparableValue, \ - less_than_comparable LessThanComparableValue, \ - less_equal_comparable LessEqualComparableValue, \ - greater_equal_comparable GreaterEqualComparableValue, \ - greater_than_comparable GreaterThanComparableValue, \ - swappable SwappableValue, hashable HashableValue> \ - constexpr type ConformanceProfile< \ - DefaultConstructibleValue, MoveConstructibleValue, \ - CopyConstructibleValue, MoveAssignableValue, CopyAssignableValue, \ - DestructibleValue, EqualityComparableValue, InequalityComparableValue, \ - LessThanComparableValue, LessEqualComparableValue, \ - GreaterEqualComparableValue, GreaterThanComparableValue, SwappableValue, \ - HashableValue>::name - -#define ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(type) \ - ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL(type, \ - type##_support); \ - ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL(bool, is_##type) - -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(default_constructible); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(move_constructible); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(copy_constructible); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(move_assignable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(copy_assignable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(destructible); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(equality_comparable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(inequality_comparable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(less_than_comparable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(less_equal_comparable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(greater_equal_comparable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(greater_than_comparable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(swappable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(hashable); - -#undef ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF -#undef ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL - -// Retrieve the enum with the minimum underlying value. -// Note: std::min is not constexpr in C++11, which is why this is necessary. -template <class H> -constexpr H MinEnum(H head) { - return head; -} - -template <class H, class N, class... T> -constexpr H MinEnum(H head, N next, T... tail) { - return (UnderlyingValue)(head) < (UnderlyingValue)(next) - ? (MinEnum)(head, tail...) - : (MinEnum)(next, tail...); -} - -template <class... Profs> -struct MinimalProfiles { - static constexpr default_constructible - default_constructible_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::default_constructible_support...); - - static constexpr move_constructible move_constructible_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::move_constructible_support...); - - static constexpr copy_constructible copy_constructible_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::copy_constructible_support...); - - static constexpr move_assignable move_assignable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::move_assignable_support...); - - static constexpr copy_assignable copy_assignable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::copy_assignable_support...); - - static constexpr destructible destructible_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::destructible_support...); - - static constexpr equality_comparable equality_comparable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::equality_comparable_support...); - - static constexpr inequality_comparable - inequality_comparable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::inequality_comparable_support...); - - static constexpr less_than_comparable - less_than_comparable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::less_than_comparable_support...); - - static constexpr less_equal_comparable - less_equal_comparable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::less_equal_comparable_support...); - - static constexpr greater_equal_comparable - greater_equal_comparable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::greater_equal_comparable_support...); - - static constexpr greater_than_comparable - greater_than_comparable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::greater_than_comparable_support...); - - static constexpr swappable swappable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::swappable_support...); - - static constexpr hashable hashable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::hashable_support...); - - using properties = ConformanceProfile< - default_constructible_support, move_constructible_support, - copy_constructible_support, move_assignable_support, - copy_assignable_support, destructible_support, - equality_comparable_support, inequality_comparable_support, - less_than_comparable_support, less_equal_comparable_support, - greater_equal_comparable_support, greater_than_comparable_support, - swappable_support, hashable_support>; -}; - -// Retrieve the enum with the greatest underlying value. -// Note: std::max is not constexpr in C++11, which is why this is necessary. -template <class H> -constexpr H MaxEnum(H head) { - return head; -} - -template <class H, class N, class... T> -constexpr H MaxEnum(H head, N next, T... tail) { - return (UnderlyingValue)(next) < (UnderlyingValue)(head) - ? (MaxEnum)(head, tail...) - : (MaxEnum)(next, tail...); -} - -template <class... Profs> -struct CombineProfilesImpl { - static constexpr default_constructible - default_constructible_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::default_constructible_support...); - - static constexpr move_constructible move_constructible_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::move_constructible_support...); - - static constexpr copy_constructible copy_constructible_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::copy_constructible_support...); - - static constexpr move_assignable move_assignable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::move_assignable_support...); - - static constexpr copy_assignable copy_assignable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::copy_assignable_support...); - - static constexpr destructible destructible_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::destructible_support...); - - static constexpr equality_comparable equality_comparable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::equality_comparable_support...); - - static constexpr inequality_comparable - inequality_comparable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::inequality_comparable_support...); - - static constexpr less_than_comparable - less_than_comparable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::less_than_comparable_support...); - - static constexpr less_equal_comparable - less_equal_comparable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::less_equal_comparable_support...); - - static constexpr greater_equal_comparable - greater_equal_comparable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::greater_equal_comparable_support...); - - static constexpr greater_than_comparable - greater_than_comparable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::greater_than_comparable_support...); - - static constexpr swappable swappable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::swappable_support...); - - static constexpr hashable hashable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::hashable_support...); - - using properties = ConformanceProfile< - default_constructible_support, move_constructible_support, - copy_constructible_support, move_assignable_support, - copy_assignable_support, destructible_support, - equality_comparable_support, inequality_comparable_support, - less_than_comparable_support, less_equal_comparable_support, - greater_equal_comparable_support, greater_than_comparable_support, - swappable_support, hashable_support>; -}; - -// NOTE: We use this as opposed to a direct alias of CombineProfilesImpl so that -// when named aliases of CombineProfiles are created (such as in -// conformance_aliases.h), we only pay for the combination algorithm on the -// profiles that are actually used. -template <class... Profs> -struct CombineProfiles { - using profile_alias_of = CombineProfilesImpl<Profs...>; -}; - -template <> -struct CombineProfiles<> { - using properties = ConformanceProfile<>; -}; - -template <class Profile, class Tag> -struct StrongProfileTypedef { - using properties = PropertiesOfT<Profile>; -}; - -template <class T, class /*Enabler*/ = void> -struct IsProfileImpl : std::false_type {}; - -template <class T> -struct IsProfileImpl<T, absl::void_t<PropertiesOfT<T>>> : std::true_type {}; - -template <class T> -struct IsProfile : IsProfileImpl<T>::type {}; - -// A tag that describes which set of properties we will check when the user -// requires a strict match in conformance (as opposed to a loose match which -// allows more-refined support of any given operation). -// -// Currently only the RegularityDomain exists and it includes all operations -// that the conformance testing suite knows about. The intent is that if the -// suite is expanded to support extension, such as for checking conformance of -// concepts like Iterators or Containers, additional corresponding domains can -// be created. -struct RegularityDomain {}; - -} // namespace types_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TYPES_INTERNAL_CONFORMANCE_PROFILE_H_ diff --git a/third_party/abseil_cpp/absl/types/internal/conformance_testing.h b/third_party/abseil_cpp/absl/types/internal/conformance_testing.h deleted file mode 100644 index 487b0f786b48..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/conformance_testing.h +++ /dev/null @@ -1,1386 +0,0 @@ -// Copyright 2019 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------- -// conformance_testing.h -// ----------------------------------------------------------------------------- -// - -#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_H_ -#define ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_H_ - -//////////////////////////////////////////////////////////////////////////////// -// // -// Many templates in this file take a `T` and a `Prof` type as explicit // -// template arguments. These are a type to be checked and a // -// "Regularity Profile" that describes what operations that type `T` is // -// expected to support. See "regularity_profiles.h" for more details // -// regarding Regularity Profiles. // -// // -//////////////////////////////////////////////////////////////////////////////// - -#include <cstddef> -#include <set> -#include <tuple> -#include <type_traits> -#include <utility> - -#include "gtest/gtest.h" -#include "absl/meta/type_traits.h" -#include "absl/strings/ascii.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/string_view.h" -#include "absl/types/internal/conformance_aliases.h" -#include "absl/types/internal/conformance_archetype.h" -#include "absl/types/internal/conformance_profile.h" -#include "absl/types/internal/conformance_testing_helpers.h" -#include "absl/types/internal/parentheses.h" -#include "absl/types/internal/transform_args.h" -#include "absl/utility/utility.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace types_internal { - -// Returns true if the compiler incorrectly greedily instantiates constexpr -// templates in any unevaluated context. -constexpr bool constexpr_instantiation_when_unevaluated() { -#if defined(__apple_build_version__) // TODO(calabrese) Make more specific - return true; -#elif defined(__clang__) - return __clang_major__ < 4; -#elif defined(__GNUC__) - // TODO(calabrese) Figure out why gcc 7 fails (seems like a different bug) - return __GNUC__ < 5 || (__GNUC__ == 5 && __GNUC_MINOR__ < 2) || __GNUC__ >= 7; -#else - return false; -#endif -} - -// Returns true if the standard library being used incorrectly produces an error -// when instantiating the definition of a poisoned std::hash specialization. -constexpr bool poisoned_hash_fails_instantiation() { -#if defined(_MSC_VER) && !defined(_LIBCPP_VERSION) - return _MSC_VER < 1914; -#else - return false; -#endif -} - -template <class Fun> -struct GeneratorType { - decltype(std::declval<const Fun&>()()) operator()() const - noexcept(noexcept(std::declval<const Fun&>()())) { - return fun(); - } - - Fun fun; - const char* description; -}; - -// A "make" function for the GeneratorType template that deduces the function -// object type. -template <class Fun, - absl::enable_if_t<IsNullaryCallable<Fun>::value>** = nullptr> -GeneratorType<Fun> Generator(Fun fun, const char* description) { - return GeneratorType<Fun>{absl::move(fun), description}; -} - -// A type that contains a set of nullary function objects that each return an -// instance of the same type and value (though possibly different -// representations, such as +0 and -0 or two vectors with the same elements but -// with different capacities). -template <class... Funs> -struct EquivalenceClassType { - std::tuple<GeneratorType<Funs>...> generators; -}; - -// A "make" function for the EquivalenceClassType template that deduces the -// function object types and is constrained such that a user can only pass in -// function objects that all have the same return type. -template <class... Funs, absl::enable_if_t<AreGeneratorsWithTheSameReturnType< - Funs...>::value>** = nullptr> -EquivalenceClassType<Funs...> EquivalenceClass(GeneratorType<Funs>... funs) { - return {std::make_tuple(absl::move(funs)...)}; -} - -// A type that contains an ordered series of EquivalenceClassTypes, from -// smallest value to largest value. -template <class... EqClasses> -struct OrderedEquivalenceClasses { - std::tuple<EqClasses...> eq_classes; -}; - -// An object containing the parts of a given (name, initialization expression), -// and is capable of generating a string that describes the given. -struct GivenDeclaration { - std::string outputDeclaration(std::size_t width) const { - const std::size_t indent_size = 2; - std::string result = absl::StrCat(" ", name); - - if (!expression.empty()) { - // Indent - result.resize(indent_size + width, ' '); - absl::StrAppend(&result, " = ", expression, ";\n"); - } else { - absl::StrAppend(&result, ";\n"); - } - - return result; - } - - std::string name; - std::string expression; -}; - -// Produce a string that contains all of the givens of an error report. -template <class... Decls> -std::string PrepareGivenContext(const Decls&... decls) { - const std::size_t width = (std::max)({decls.name.size()...}); - return absl::StrCat("Given:\n", decls.outputDeclaration(width)..., "\n"); -} - -//////////////////////////////////////////////////////////////////////////////// -// Function objects that perform a check for each comparison operator // -//////////////////////////////////////////////////////////////////////////////// - -#define ABSL_INTERNAL_EXPECT_OP(name, op) \ - struct Expect##name { \ - template <class T> \ - void operator()(absl::string_view test_name, absl::string_view context, \ - const T& lhs, const T& rhs, absl::string_view lhs_name, \ - absl::string_view rhs_name) const { \ - if (!static_cast<bool>(lhs op rhs)) { \ - errors->addTestFailure( \ - test_name, absl::StrCat(context, \ - "**Unexpected comparison result**\n" \ - "\n" \ - "Expression:\n" \ - " ", \ - lhs_name, " " #op " ", rhs_name, \ - "\n" \ - "\n" \ - "Expected: true\n" \ - " Actual: false")); \ - } else { \ - errors->addTestSuccess(test_name); \ - } \ - } \ - \ - ConformanceErrors* errors; \ - }; \ - \ - struct ExpectNot##name { \ - template <class T> \ - void operator()(absl::string_view test_name, absl::string_view context, \ - const T& lhs, const T& rhs, absl::string_view lhs_name, \ - absl::string_view rhs_name) const { \ - if (lhs op rhs) { \ - errors->addTestFailure( \ - test_name, absl::StrCat(context, \ - "**Unexpected comparison result**\n" \ - "\n" \ - "Expression:\n" \ - " ", \ - lhs_name, " " #op " ", rhs_name, \ - "\n" \ - "\n" \ - "Expected: false\n" \ - " Actual: true")); \ - } else { \ - errors->addTestSuccess(test_name); \ - } \ - } \ - \ - ConformanceErrors* errors; \ - } - -ABSL_INTERNAL_EXPECT_OP(Eq, ==); -ABSL_INTERNAL_EXPECT_OP(Ne, !=); -ABSL_INTERNAL_EXPECT_OP(Lt, <); -ABSL_INTERNAL_EXPECT_OP(Le, <=); -ABSL_INTERNAL_EXPECT_OP(Ge, >=); -ABSL_INTERNAL_EXPECT_OP(Gt, >); - -#undef ABSL_INTERNAL_EXPECT_OP - -// A function object that verifies that two objects hash to the same value by -// way of the std::hash specialization. -struct ExpectSameHash { - template <class T> - void operator()(absl::string_view test_name, absl::string_view context, - const T& lhs, const T& rhs, absl::string_view lhs_name, - absl::string_view rhs_name) const { - if (std::hash<T>()(lhs) != std::hash<T>()(rhs)) { - errors->addTestFailure( - test_name, absl::StrCat(context, - "**Unexpected hash result**\n" - "\n" - "Expression:\n" - " std::hash<T>()(", - lhs_name, ") == std::hash<T>()(", rhs_name, - ")\n" - "\n" - "Expected: true\n" - " Actual: false")); - } else { - errors->addTestSuccess(test_name); - } - } - - ConformanceErrors* errors; -}; - -// A function template that takes two objects and verifies that each comparison -// operator behaves in a way that is consistent with equality. It has "OneWay" -// in the name because the first argument will always be the left-hand operand -// of the corresponding comparison operator and the second argument will -// always be the right-hand operand. It will never switch that order. -// At a higher level in the test suite, the one-way form is called once for each -// of the two possible orders whenever lhs and rhs are not the same initializer. -template <class T, class Prof> -void ExpectOneWayEquality(ConformanceErrors* errors, - absl::string_view test_name, - absl::string_view context, const T& lhs, const T& rhs, - absl::string_view lhs_name, - absl::string_view rhs_name) { - If<PropertiesOfT<Prof>::is_equality_comparable>::Invoke( - ExpectEq{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name); - - If<PropertiesOfT<Prof>::is_inequality_comparable>::Invoke( - ExpectNotNe{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name); - - If<PropertiesOfT<Prof>::is_less_than_comparable>::Invoke( - ExpectNotLt{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name); - - If<PropertiesOfT<Prof>::is_less_equal_comparable>::Invoke( - ExpectLe{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name); - - If<PropertiesOfT<Prof>::is_greater_equal_comparable>::Invoke( - ExpectGe{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name); - - If<PropertiesOfT<Prof>::is_greater_than_comparable>::Invoke( - ExpectNotGt{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name); - - If<PropertiesOfT<Prof>::is_hashable>::Invoke( - ExpectSameHash{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name); -} - -// A function template that takes two objects and verifies that each comparison -// operator behaves in a way that is consistent with equality. This function -// differs from ExpectOneWayEquality in that this will do checks with argument -// order reversed in addition to in-order. -template <class T, class Prof> -void ExpectEquality(ConformanceErrors* errors, absl::string_view test_name, - absl::string_view context, const T& lhs, const T& rhs, - absl::string_view lhs_name, absl::string_view rhs_name) { - (ExpectOneWayEquality<T, Prof>)(errors, test_name, context, lhs, rhs, - lhs_name, rhs_name); - (ExpectOneWayEquality<T, Prof>)(errors, test_name, context, rhs, lhs, - rhs_name, lhs_name); -} - -// Given a generator, makes sure that a generated value and a moved-from -// generated value are equal. -template <class T, class Prof> -struct ExpectMoveConstructOneGenerator { - template <class Fun> - void operator()(const Fun& generator) const { - const T object = generator(); - const T moved_object = absl::move(generator()); // Force no elision. - - (ExpectEquality<T, Prof>)(errors, "Move construction", - PrepareGivenContext( - GivenDeclaration{"const _T object", - generator.description}, - GivenDeclaration{"const _T moved_object", - std::string("std::move(") + - generator.description + - ")"}), - object, moved_object, "object", "moved_object"); - } - - ConformanceErrors* errors; -}; - -// Given a generator, makes sure that a generated value and a copied-from -// generated value are equal. -template <class T, class Prof> -struct ExpectCopyConstructOneGenerator { - template <class Fun> - void operator()(const Fun& generator) const { - const T object = generator(); - const T copied_object = static_cast<const T&>(generator()); - - (ExpectEquality<T, Prof>)(errors, "Copy construction", - PrepareGivenContext( - GivenDeclaration{"const _T object", - generator.description}, - GivenDeclaration{ - "const _T copied_object", - std::string("static_cast<const _T&>(") + - generator.description + ")"}), - object, copied_object, "object", "copied_object"); - } - - ConformanceErrors* errors; -}; - -// Default-construct and do nothing before destruction. -// -// This is useful in exercising the codepath of default construction followed by -// destruction, but does not explicitly test anything. An example of where this -// might fail is a default destructor that default-initializes a scalar and a -// destructor reads the value of that member. Sanitizers can catch this as long -// as our test attempts to execute such a case. -template <class T> -struct ExpectDefaultConstructWithDestruct { - void operator()() const { - // Scoped so that destructor gets called before reporting success. - { - T object; - static_cast<void>(object); - } - - errors->addTestSuccess("Default construction"); - } - - ConformanceErrors* errors; -}; - -// Check move-assign into a default-constructed object. -template <class T, class Prof> -struct ExpectDefaultConstructWithMoveAssign { - template <class Fun> - void operator()(const Fun& generator) const { - const T source_of_truth = generator(); - T object; - object = generator(); - - (ExpectEquality<T, Prof>)(errors, "Move assignment", - PrepareGivenContext( - GivenDeclaration{"const _T object", - generator.description}, - GivenDeclaration{"_T object", ""}, - GivenDeclaration{"object", - generator.description}), - object, source_of_truth, "std::as_const(object)", - "source_of_truth"); - } - - ConformanceErrors* errors; -}; - -// Check copy-assign into a default-constructed object. -template <class T, class Prof> -struct ExpectDefaultConstructWithCopyAssign { - template <class Fun> - void operator()(const Fun& generator) const { - const T source_of_truth = generator(); - T object; - object = static_cast<const T&>(generator()); - - (ExpectEquality<T, Prof>)(errors, "Copy assignment", - PrepareGivenContext( - GivenDeclaration{"const _T source_of_truth", - generator.description}, - GivenDeclaration{"_T object", ""}, - GivenDeclaration{ - "object", - std::string("static_cast<const _T&>(") + - generator.description + ")"}), - object, source_of_truth, "std::as_const(object)", - "source_of_truth"); - } - - ConformanceErrors* errors; -}; - -// Perform a self move-assign. -template <class T, class Prof> -struct ExpectSelfMoveAssign { - template <class Fun> - void operator()(const Fun& generator) const { - T object = generator(); - object = absl::move(object); - - // NOTE: Self move-assign results in a valid-but-unspecified state. - - (ExpectEquality<T, Prof>)(errors, "Move assignment", - PrepareGivenContext( - GivenDeclaration{"_T object", - generator.description}, - GivenDeclaration{"object", - "std::move(object)"}), - object, object, "object", "object"); - } - - ConformanceErrors* errors; -}; - -// Perform a self copy-assign. -template <class T, class Prof> -struct ExpectSelfCopyAssign { - template <class Fun> - void operator()(const Fun& generator) const { - const T source_of_truth = generator(); - T object = generator(); - const T& const_object = object; - object = const_object; - - (ExpectEquality<T, Prof>)(errors, "Copy assignment", - PrepareGivenContext( - GivenDeclaration{"const _T source_of_truth", - generator.description}, - GivenDeclaration{"_T object", - generator.description}, - GivenDeclaration{"object", - "std::as_const(object)"}), - const_object, source_of_truth, - "std::as_const(object)", "source_of_truth"); - } - - ConformanceErrors* errors; -}; - -// Perform a self-swap. -template <class T, class Prof> -struct ExpectSelfSwap { - template <class Fun> - void operator()(const Fun& generator) const { - const T source_of_truth = generator(); - T object = generator(); - - type_traits_internal::Swap(object, object); - - std::string preliminary_info = absl::StrCat( - PrepareGivenContext( - GivenDeclaration{"const _T source_of_truth", generator.description}, - GivenDeclaration{"_T object", generator.description}), - "After performing a self-swap:\n" - " using std::swap;\n" - " swap(object, object);\n" - "\n"); - - (ExpectEquality<T, Prof>)(errors, "Swap", std::move(preliminary_info), - object, source_of_truth, "std::as_const(object)", - "source_of_truth"); - } - - ConformanceErrors* errors; -}; - -// Perform each of the single-generator checks when necessary operations are -// supported. -template <class T, class Prof> -struct ExpectSelfComparison { - template <class Fun> - void operator()(const Fun& generator) const { - const T object = generator(); - (ExpectOneWayEquality<T, Prof>)(errors, "Comparison", - PrepareGivenContext(GivenDeclaration{ - "const _T object", - generator.description}), - object, object, "object", "object"); - } - - ConformanceErrors* errors; -}; - -// Perform each of the single-generator checks when necessary operations are -// supported. -template <class T, class Prof> -struct ExpectConsistency { - template <class Fun> - void operator()(const Fun& generator) const { - If<PropertiesOfT<Prof>::is_move_constructible>::Invoke( - ExpectMoveConstructOneGenerator<T, Prof>{errors}, generator); - - If<PropertiesOfT<Prof>::is_copy_constructible>::Invoke( - ExpectCopyConstructOneGenerator<T, Prof>{errors}, generator); - - If<PropertiesOfT<Prof>::is_default_constructible && - PropertiesOfT<Prof>::is_move_assignable>:: - Invoke(ExpectDefaultConstructWithMoveAssign<T, Prof>{errors}, - generator); - - If<PropertiesOfT<Prof>::is_default_constructible && - PropertiesOfT<Prof>::is_copy_assignable>:: - Invoke(ExpectDefaultConstructWithCopyAssign<T, Prof>{errors}, - generator); - - If<PropertiesOfT<Prof>::is_move_assignable>::Invoke( - ExpectSelfMoveAssign<T, Prof>{errors}, generator); - - If<PropertiesOfT<Prof>::is_copy_assignable>::Invoke( - ExpectSelfCopyAssign<T, Prof>{errors}, generator); - - If<PropertiesOfT<Prof>::is_swappable>::Invoke( - ExpectSelfSwap<T, Prof>{errors}, generator); - } - - ConformanceErrors* errors; -}; - -// Check move-assign with two different values. -template <class T, class Prof> -struct ExpectMoveAssign { - template <class Fun0, class Fun1> - void operator()(const Fun0& generator0, const Fun1& generator1) const { - const T source_of_truth1 = generator1(); - T object = generator0(); - object = generator1(); - - (ExpectEquality<T, Prof>)(errors, "Move assignment", - PrepareGivenContext( - GivenDeclaration{"const _T source_of_truth1", - generator1.description}, - GivenDeclaration{"_T object", - generator0.description}, - GivenDeclaration{"object", - generator1.description}), - object, source_of_truth1, "std::as_const(object)", - "source_of_truth1"); - } - - ConformanceErrors* errors; -}; - -// Check copy-assign with two different values. -template <class T, class Prof> -struct ExpectCopyAssign { - template <class Fun0, class Fun1> - void operator()(const Fun0& generator0, const Fun1& generator1) const { - const T source_of_truth1 = generator1(); - T object = generator0(); - object = static_cast<const T&>(generator1()); - - (ExpectEquality<T, Prof>)(errors, "Copy assignment", - PrepareGivenContext( - GivenDeclaration{"const _T source_of_truth1", - generator1.description}, - GivenDeclaration{"_T object", - generator0.description}, - GivenDeclaration{ - "object", - std::string("static_cast<const _T&>(") + - generator1.description + ")"}), - object, source_of_truth1, "std::as_const(object)", - "source_of_truth1"); - } - - ConformanceErrors* errors; -}; - -// Check swap with two different values. -template <class T, class Prof> -struct ExpectSwap { - template <class Fun0, class Fun1> - void operator()(const Fun0& generator0, const Fun1& generator1) const { - const T source_of_truth0 = generator0(); - const T source_of_truth1 = generator1(); - T object0 = generator0(); - T object1 = generator1(); - - type_traits_internal::Swap(object0, object1); - - const std::string context = - PrepareGivenContext( - GivenDeclaration{"const _T source_of_truth0", - generator0.description}, - GivenDeclaration{"const _T source_of_truth1", - generator1.description}, - GivenDeclaration{"_T object0", generator0.description}, - GivenDeclaration{"_T object1", generator1.description}) + - "After performing a swap:\n" - " using std::swap;\n" - " swap(object0, object1);\n" - "\n"; - - (ExpectEquality<T, Prof>)(errors, "Swap", context, object0, - source_of_truth1, "std::as_const(object0)", - "source_of_truth1"); - (ExpectEquality<T, Prof>)(errors, "Swap", context, object1, - source_of_truth0, "std::as_const(object1)", - "source_of_truth0"); - } - - ConformanceErrors* errors; -}; - -// Validate that `generator0` and `generator1` produce values that are equal. -template <class T, class Prof> -struct ExpectEquivalenceClassComparison { - template <class Fun0, class Fun1> - void operator()(const Fun0& generator0, const Fun1& generator1) const { - const T object0 = generator0(); - const T object1 = generator1(); - - (ExpectEquality<T, Prof>)(errors, "Comparison", - PrepareGivenContext( - GivenDeclaration{"const _T object0", - generator0.description}, - GivenDeclaration{"const _T object1", - generator1.description}), - object0, object1, "object0", "object1"); - } - - ConformanceErrors* errors; -}; - -// Validate that all objects in the same equivalence-class have the same value. -template <class T, class Prof> -struct ExpectEquivalenceClassConsistency { - template <class Fun0, class Fun1> - void operator()(const Fun0& generator0, const Fun1& generator1) const { - If<PropertiesOfT<Prof>::is_move_assignable>::Invoke( - ExpectMoveAssign<T, Prof>{errors}, generator0, generator1); - - If<PropertiesOfT<Prof>::is_copy_assignable>::Invoke( - ExpectCopyAssign<T, Prof>{errors}, generator0, generator1); - - If<PropertiesOfT<Prof>::is_swappable>::Invoke(ExpectSwap<T, Prof>{errors}, - generator0, generator1); - } - - ConformanceErrors* errors; -}; - -// Given a "lesser" object and a "greater" object, perform every combination of -// comparison operators supported for the type, expecting consistent results. -template <class T, class Prof> -void ExpectOrdered(ConformanceErrors* errors, absl::string_view context, - const T& small, const T& big, absl::string_view small_name, - absl::string_view big_name) { - const absl::string_view test_name = "Comparison"; - - If<PropertiesOfT<Prof>::is_equality_comparable>::Invoke( - ExpectNotEq{errors}, test_name, context, small, big, small_name, - big_name); - If<PropertiesOfT<Prof>::is_equality_comparable>::Invoke( - ExpectNotEq{errors}, test_name, context, big, small, big_name, - small_name); - - If<PropertiesOfT<Prof>::is_inequality_comparable>::Invoke( - ExpectNe{errors}, test_name, context, small, big, small_name, big_name); - If<PropertiesOfT<Prof>::is_inequality_comparable>::Invoke( - ExpectNe{errors}, test_name, context, big, small, big_name, small_name); - - If<PropertiesOfT<Prof>::is_less_than_comparable>::Invoke( - ExpectLt{errors}, test_name, context, small, big, small_name, big_name); - If<PropertiesOfT<Prof>::is_less_than_comparable>::Invoke( - ExpectNotLt{errors}, test_name, context, big, small, big_name, - small_name); - - If<PropertiesOfT<Prof>::is_less_equal_comparable>::Invoke( - ExpectLe{errors}, test_name, context, small, big, small_name, big_name); - If<PropertiesOfT<Prof>::is_less_equal_comparable>::Invoke( - ExpectNotLe{errors}, test_name, context, big, small, big_name, - small_name); - - If<PropertiesOfT<Prof>::is_greater_equal_comparable>::Invoke( - ExpectNotGe{errors}, test_name, context, small, big, small_name, - big_name); - If<PropertiesOfT<Prof>::is_greater_equal_comparable>::Invoke( - ExpectGe{errors}, test_name, context, big, small, big_name, small_name); - - If<PropertiesOfT<Prof>::is_greater_than_comparable>::Invoke( - ExpectNotGt{errors}, test_name, context, small, big, small_name, - big_name); - If<PropertiesOfT<Prof>::is_greater_than_comparable>::Invoke( - ExpectGt{errors}, test_name, context, big, small, big_name, small_name); -} - -// For every two elements of an equivalence class, makes sure that those two -// elements compare equal, including checks with the same argument passed as -// both operands. -template <class T, class Prof> -struct ExpectEquivalenceClassComparisons { - template <class... Funs> - void operator()(EquivalenceClassType<Funs...> eq_class) const { - (ForEachTupleElement)(ExpectSelfComparison<T, Prof>{errors}, - eq_class.generators); - - (ForEveryTwo)(ExpectEquivalenceClassComparison<T, Prof>{errors}, - eq_class.generators); - } - - ConformanceErrors* errors; -}; - -// For every element of an equivalence class, makes sure that the element is -// self-consistent (in other words, if any of move/copy/swap are defined, -// perform those operations and make such that results and operands still -// compare equal to known values whenever it is required for that operation. -template <class T, class Prof> -struct ExpectEquivalenceClass { - template <class... Funs> - void operator()(EquivalenceClassType<Funs...> eq_class) const { - (ForEachTupleElement)(ExpectConsistency<T, Prof>{errors}, - eq_class.generators); - - (ForEveryTwo)(ExpectEquivalenceClassConsistency<T, Prof>{errors}, - eq_class.generators); - } - - ConformanceErrors* errors; -}; - -// Validate that the passed-in argument is a generator of a greater value than -// the one produced by the "small_gen" datamember with respect to all of the -// comparison operators that Prof requires, with both argument orders to test. -template <class T, class Prof, class SmallGenerator> -struct ExpectBiggerGeneratorThanComparisons { - template <class BigGenerator> - void operator()(BigGenerator big_gen) const { - const T small = small_gen(); - const T big = big_gen(); - - (ExpectOrdered<T, Prof>)(errors, - PrepareGivenContext( - GivenDeclaration{"const _T small", - small_gen.description}, - GivenDeclaration{"const _T big", - big_gen.description}), - small, big, "small", "big"); - } - - SmallGenerator small_gen; - ConformanceErrors* errors; -}; - -// Perform all of the move, copy, and swap checks on the value generated by -// `small_gen` and the value generated by `big_gen`. -template <class T, class Prof, class SmallGenerator> -struct ExpectBiggerGeneratorThan { - template <class BigGenerator> - void operator()(BigGenerator big_gen) const { - If<PropertiesOfT<Prof>::is_move_assignable>::Invoke( - ExpectMoveAssign<T, Prof>{errors}, small_gen, big_gen); - If<PropertiesOfT<Prof>::is_move_assignable>::Invoke( - ExpectMoveAssign<T, Prof>{errors}, big_gen, small_gen); - - If<PropertiesOfT<Prof>::is_copy_assignable>::Invoke( - ExpectCopyAssign<T, Prof>{errors}, small_gen, big_gen); - If<PropertiesOfT<Prof>::is_copy_assignable>::Invoke( - ExpectCopyAssign<T, Prof>{errors}, big_gen, small_gen); - - If<PropertiesOfT<Prof>::is_swappable>::Invoke(ExpectSwap<T, Prof>{errors}, - small_gen, big_gen); - } - - SmallGenerator small_gen; - ConformanceErrors* errors; -}; - -// Validate that the result of a generator is greater than the results of all -// generators in an equivalence class with respect to comparisons. -template <class T, class Prof, class SmallGenerator> -struct ExpectBiggerGeneratorThanEqClassesComparisons { - template <class BigEqClass> - void operator()(BigEqClass big_eq_class) const { - (ForEachTupleElement)( - ExpectBiggerGeneratorThanComparisons<T, Prof, SmallGenerator>{small_gen, - errors}, - big_eq_class.generators); - } - - SmallGenerator small_gen; - ConformanceErrors* errors; -}; - -// Validate that the non-comparison binary operations required by Prof are -// correct for the result of each generator of big_eq_class and a generator of -// the logically smaller value returned by small_gen. -template <class T, class Prof, class SmallGenerator> -struct ExpectBiggerGeneratorThanEqClasses { - template <class BigEqClass> - void operator()(BigEqClass big_eq_class) const { - (ForEachTupleElement)( - ExpectBiggerGeneratorThan<T, Prof, SmallGenerator>{small_gen, errors}, - big_eq_class.generators); - } - - SmallGenerator small_gen; - ConformanceErrors* errors; -}; - -// Validate that each equivalence class that is passed is logically less than -// the equivalence classes that comes later on in the argument list. -template <class T, class Prof> -struct ExpectOrderedEquivalenceClassesComparisons { - template <class... BigEqClasses> - struct Impl { - // Validate that the value produced by `small_gen` is less than all of the - // values generated by those of the logically larger equivalence classes. - template <class SmallGenerator> - void operator()(SmallGenerator small_gen) const { - (ForEachTupleElement)(ExpectBiggerGeneratorThanEqClassesComparisons< - T, Prof, SmallGenerator>{small_gen, errors}, - big_eq_classes); - } - - std::tuple<BigEqClasses...> big_eq_classes; - ConformanceErrors* errors; - }; - - // When given no equivalence classes, no validation is necessary. - void operator()() const {} - - template <class SmallEqClass, class... BigEqClasses> - void operator()(SmallEqClass small_eq_class, - BigEqClasses... big_eq_classes) const { - // For each generator in the first equivalence class, make sure that it is - // less than each of those in the logically greater equivalence classes. - (ForEachTupleElement)( - Impl<BigEqClasses...>{std::make_tuple(absl::move(big_eq_classes)...), - errors}, - small_eq_class.generators); - - // Recurse so that all equivalence class combinations are checked. - (*this)(absl::move(big_eq_classes)...); - } - - ConformanceErrors* errors; -}; - -// Validate that the non-comparison binary operations required by Prof are -// correct for the result of each generator of big_eq_classes and a generator of -// the logically smaller value returned by small_gen. -template <class T, class Prof> -struct ExpectOrderedEquivalenceClasses { - template <class... BigEqClasses> - struct Impl { - template <class SmallGenerator> - void operator()(SmallGenerator small_gen) const { - (ForEachTupleElement)( - ExpectBiggerGeneratorThanEqClasses<T, Prof, SmallGenerator>{small_gen, - errors}, - big_eq_classes); - } - - std::tuple<BigEqClasses...> big_eq_classes; - ConformanceErrors* errors; - }; - - // Check that small_eq_class is logically consistent and also is logically - // less than all values in big_eq_classes. - template <class SmallEqClass, class... BigEqClasses> - void operator()(SmallEqClass small_eq_class, - BigEqClasses... big_eq_classes) const { - (ForEachTupleElement)( - Impl<BigEqClasses...>{std::make_tuple(absl::move(big_eq_classes)...), - errors}, - small_eq_class.generators); - - (*this)(absl::move(big_eq_classes)...); - } - - // Terminating case of operator(). - void operator()() const {} - - ConformanceErrors* errors; -}; - -// Validate that a type meets the syntactic requirements of std::hash if the -// range of profiles requires it. -template <class T, class MinProf, class MaxProf> -struct ExpectHashable { - void operator()() const { - ExpectModelOfHashable<T, MinProf, MaxProf>(errors); - } - - ConformanceErrors* errors; -}; - -// Validate that the type `T` meets all of the requirements associated with -// `MinProf` and without going beyond the syntactic properties of `MaxProf`. -template <class T, class MinProf, class MaxProf> -struct ExpectModels { - void operator()(ConformanceErrors* errors) const { - ExpectModelOfDefaultConstructible<T, MinProf, MaxProf>(errors); - ExpectModelOfMoveConstructible<T, MinProf, MaxProf>(errors); - ExpectModelOfCopyConstructible<T, MinProf, MaxProf>(errors); - ExpectModelOfMoveAssignable<T, MinProf, MaxProf>(errors); - ExpectModelOfCopyAssignable<T, MinProf, MaxProf>(errors); - ExpectModelOfDestructible<T, MinProf, MaxProf>(errors); - ExpectModelOfEqualityComparable<T, MinProf, MaxProf>(errors); - ExpectModelOfInequalityComparable<T, MinProf, MaxProf>(errors); - ExpectModelOfLessThanComparable<T, MinProf, MaxProf>(errors); - ExpectModelOfLessEqualComparable<T, MinProf, MaxProf>(errors); - ExpectModelOfGreaterEqualComparable<T, MinProf, MaxProf>(errors); - ExpectModelOfGreaterThanComparable<T, MinProf, MaxProf>(errors); - ExpectModelOfSwappable<T, MinProf, MaxProf>(errors); - - // Only check hashability on compilers that have a compliant default-hash. - If<!poisoned_hash_fails_instantiation()>::Invoke( - ExpectHashable<T, MinProf, MaxProf>{errors}); - } -}; - -// A metafunction that yields a Profile matching the set of properties that are -// safe to be checked (lack-of-hashability is only checked on standard library -// implementations that are standards compliant in that they provide a std::hash -// primary template that is SFINAE-friendly) -template <class LogicalProf, class T> -struct MinimalCheckableProfile { - using type = - MinimalProfiles<PropertiesOfT<LogicalProf>, - PropertiesOfT<SyntacticConformanceProfileOf< - T, !PropertiesOfT<LogicalProf>::is_hashable && - poisoned_hash_fails_instantiation() - ? CheckHashability::no - : CheckHashability::yes>>>; -}; - -// An identity metafunction -template <class T> -struct Always { - using type = T; -}; - -// Validate the T meets all of the necessary requirements of LogicalProf, with -// syntactic requirements defined by the profile range [MinProf, MaxProf]. -template <class T, class LogicalProf, class MinProf, class MaxProf, - class... EqClasses> -ConformanceErrors ExpectRegularityImpl( - OrderedEquivalenceClasses<EqClasses...> vals) { - ConformanceErrors errors((NameOf<T>())); - - If<!constexpr_instantiation_when_unevaluated()>::Invoke( - ExpectModels<T, MinProf, MaxProf>(), &errors); - - using minimal_profile = typename absl::conditional_t< - constexpr_instantiation_when_unevaluated(), Always<LogicalProf>, - MinimalCheckableProfile<LogicalProf, T>>::type; - - If<PropertiesOfT<minimal_profile>::is_default_constructible>::Invoke( - ExpectDefaultConstructWithDestruct<T>{&errors}); - - ////////////////////////////////////////////////////////////////////////////// - // Perform all comparison checks first, since later checks depend on their - // correctness. - // - // Check all of the comparisons for all values in the same equivalence - // class (equal with respect to comparison operators and hash the same). - (ForEachTupleElement)( - ExpectEquivalenceClassComparisons<T, minimal_profile>{&errors}, - vals.eq_classes); - - // Check all of the comparisons for each combination of values that are in - // different equivalence classes (not equal with respect to comparison - // operators). - absl::apply( - ExpectOrderedEquivalenceClassesComparisons<T, minimal_profile>{&errors}, - vals.eq_classes); - // - ////////////////////////////////////////////////////////////////////////////// - - // Perform remaining checks, relying on comparisons. - // TODO(calabrese) short circuit if any comparisons above failed. - (ForEachTupleElement)(ExpectEquivalenceClass<T, minimal_profile>{&errors}, - vals.eq_classes); - - absl::apply(ExpectOrderedEquivalenceClasses<T, minimal_profile>{&errors}, - vals.eq_classes); - - return errors; -} - -// A type that represents a range of profiles that are acceptable to be matched. -// -// `MinProf` is the minimum set of syntactic requirements that must be met. -// -// `MaxProf` is the maximum set of syntactic requirements that must be met. -// This maximum is particularly useful for certain "strictness" checking. Some -// examples for when this is useful: -// -// * Making sure that a type is move-only (rather than simply movable) -// -// * Making sure that a member function is *not* noexcept in cases where it -// cannot be noexcept, such as if a dependent datamember has certain -// operations that are not noexcept. -// -// * Making sure that a type tightly matches a spec, such as the standard. -// -// `LogicalProf` is the Profile for which run-time testing is to take place. -// -// Note: The reason for `LogicalProf` is because it is often the case, when -// dealing with templates, that a declaration of a given operation is specified, -// but whose body would fail to instantiate. Examples include the -// copy-constructor of a standard container when the element-type is move-only, -// or the comparison operators of a standard container when the element-type -// does not have the necessary comparison operations defined. The `LogicalProf` -// parameter allows us to capture the intent of what should be tested at -// run-time, even in the cases where syntactically it might otherwise appear as -// though the type undergoing testing supports more than it actually does. -template <class LogicalProf, class MinProf = LogicalProf, - class MaxProf = MinProf> -struct ProfileRange { - using logical_profile = LogicalProf; - using min_profile = MinProf; - using max_profile = MaxProf; -}; - -// Similar to ProfileRange except that it creates a profile range that is -// coupled with a Domain and is used when testing that a type matches exactly -// the "minimum" requirements of LogicalProf. -template <class StrictnessDomain, class LogicalProf, - class MinProf = LogicalProf, class MaxProf = MinProf> -struct StrictProfileRange { - // We do not yet support extension. - static_assert( - std::is_same<StrictnessDomain, RegularityDomain>::value, - "Currently, the only valid StrictnessDomain is RegularityDomain."); - using strictness_domain = StrictnessDomain; - using logical_profile = LogicalProf; - using min_profile = MinProf; - using max_profile = MaxProf; -}; - -//////////////////////////////////////////////////////////////////////////////// -// -// A metafunction that creates a StrictProfileRange from a Domain and either a -// Profile or ProfileRange. -template <class StrictnessDomain, class ProfOrRange> -struct MakeStrictProfileRange; - -template <class StrictnessDomain, class LogicalProf> -struct MakeStrictProfileRange { - using type = StrictProfileRange<StrictnessDomain, LogicalProf>; -}; - -template <class StrictnessDomain, class LogicalProf, class MinProf, - class MaxProf> -struct MakeStrictProfileRange<StrictnessDomain, - ProfileRange<LogicalProf, MinProf, MaxProf>> { - using type = - StrictProfileRange<StrictnessDomain, LogicalProf, MinProf, MaxProf>; -}; - -template <class StrictnessDomain, class ProfOrRange> -using MakeStrictProfileRangeT = - typename MakeStrictProfileRange<StrictnessDomain, ProfOrRange>::type; -// -//////////////////////////////////////////////////////////////////////////////// - -// A profile in the RegularityDomain with the strongest possible requirements. -using MostStrictProfile = - CombineProfiles<TriviallyCompleteProfile, NothrowComparableProfile>; - -// Forms a ProfileRange that treats the Profile as the bare minimum requirements -// of a type. -template <class LogicalProf, class MinProf = LogicalProf> -using LooseProfileRange = StrictProfileRange<RegularityDomain, LogicalProf, - MinProf, MostStrictProfile>; - -template <class Prof> -using MakeLooseProfileRangeT = Prof; - -//////////////////////////////////////////////////////////////////////////////// -// -// The following classes implement the metafunction ProfileRangeOfT<T> that -// takes either a Profile or ProfileRange and yields the ProfileRange to be -// used during testing. -// -template <class T, class /*Enabler*/ = void> -struct ProfileRangeOfImpl; - -template <class T> -struct ProfileRangeOfImpl<T, absl::void_t<PropertiesOfT<T>>> { - using type = LooseProfileRange<T>; -}; - -template <class T> -struct ProfileRangeOf : ProfileRangeOfImpl<T> {}; - -template <class StrictnessDomain, class LogicalProf, class MinProf, - class MaxProf> -struct ProfileRangeOf< - StrictProfileRange<StrictnessDomain, LogicalProf, MinProf, MaxProf>> { - using type = - StrictProfileRange<StrictnessDomain, LogicalProf, MinProf, MaxProf>; -}; - -template <class T> -using ProfileRangeOfT = typename ProfileRangeOf<T>::type; -// -//////////////////////////////////////////////////////////////////////////////// - -// Extract the logical profile of a range (what will be runtime tested). -template <class T> -using LogicalProfileOfT = typename ProfileRangeOfT<T>::logical_profile; - -// Extract the minimal syntactic profile of a range (error if not at least). -template <class T> -using MinProfileOfT = typename ProfileRangeOfT<T>::min_profile; - -// Extract the maximum syntactic profile of a range (error if more than). -template <class T> -using MaxProfileOfT = typename ProfileRangeOfT<T>::max_profile; - -//////////////////////////////////////////////////////////////////////////////// -// -template <class T> -struct IsProfileOrProfileRange : IsProfile<T>::type {}; - -template <class StrictnessDomain, class LogicalProf, class MinProf, - class MaxProf> -struct IsProfileOrProfileRange< - StrictProfileRange<StrictnessDomain, LogicalProf, MinProf, MaxProf>> - : std::true_type {}; -// -//////////////////////////////////////////////////////////////////////////////// - -// TODO(calabrese): Consider naming the functions in this class the same as -// the macros (defined later on) so that auto-complete leads to the correct name -// and so that a user cannot accidentally call a function rather than the macro -// form. -template <bool ExpectSuccess, class T, class... EqClasses> -struct ExpectConformanceOf { - // Add a value to be tested. Subsequent calls to this function on the same - // object must specify logically "larger" values with respect to the - // comparison operators of the type, if any. - // - // NOTE: This function should not be called directly. A stateless lambda is - // implicitly formed and passed when using the INITIALIZER macro at the bottom - // of this file. - template <class Fun, - absl::enable_if_t<std::is_same< - ResultOfGeneratorT<GeneratorType<Fun>>, T>::value>** = nullptr> - ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses..., - EquivalenceClassType<Fun>> - initializer(GeneratorType<Fun> fun) && { - return { - {std::tuple_cat(absl::move(ordered_vals.eq_classes), - std::make_tuple((EquivalenceClass)(absl::move(fun))))}, - std::move(expected_failed_tests)}; - } - - template <class... TestNames, - absl::enable_if_t<!ExpectSuccess && sizeof...(EqClasses) == 0 && - absl::conjunction<std::is_convertible< - TestNames, absl::string_view>...>::value>** = - nullptr> - ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses...> - due_to(TestNames&&... test_names) && { - (InsertEach)(&expected_failed_tests, - absl::AsciiStrToLower(absl::string_view(test_names))...); - - return {absl::move(ordered_vals), std::move(expected_failed_tests)}; - } - - template <class... TestNames, int = 0, // MSVC disambiguator - absl::enable_if_t<ExpectSuccess && sizeof...(EqClasses) == 0 && - absl::conjunction<std::is_convertible< - TestNames, absl::string_view>...>::value>** = - nullptr> - ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses...> - due_to(TestNames&&... test_names) && { - // TODO(calabrese) Instead have DUE_TO only exist via a CRTP base. - // This would produce better errors messages than the static_assert. - static_assert(!ExpectSuccess, - "DUE_TO cannot be called when conformance is expected -- did " - "you mean to use ASSERT_NONCONFORMANCE_OF?"); - } - - // Add a value to be tested. Subsequent calls to this function on the same - // object must specify logically "larger" values with respect to the - // comparison operators of the type, if any. - // - // NOTE: This function should not be called directly. A stateful lambda is - // implicitly formed and passed when using the INITIALIZER macro at the bottom - // of this file. - template <class Fun, - absl::enable_if_t<std::is_same< - ResultOfGeneratorT<GeneratorType<Fun>>, T>::value>** = nullptr> - ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses..., - EquivalenceClassType<Fun>> - dont_class_directly_stateful_initializer(GeneratorType<Fun> fun) && { - return { - {std::tuple_cat(absl::move(ordered_vals.eq_classes), - std::make_tuple((EquivalenceClass)(absl::move(fun))))}, - std::move(expected_failed_tests)}; - } - - // Add a set of value to be tested, where each value is equal with respect to - // the comparison operators and std::hash specialization, if defined. - template < - class... Funs, - absl::void_t<absl::enable_if_t<std::is_same< - ResultOfGeneratorT<GeneratorType<Funs>>, T>::value>...>** = nullptr> - ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses..., - EquivalenceClassType<Funs...>> - equivalence_class(GeneratorType<Funs>... funs) && { - return {{std::tuple_cat( - absl::move(ordered_vals.eq_classes), - std::make_tuple((EquivalenceClass)(absl::move(funs)...)))}, - std::move(expected_failed_tests)}; - } - - // Execute the tests for the captured set of values, strictly matching a range - // of expected profiles in a given domain. - template < - class ProfRange, - absl::enable_if_t<IsProfileOrProfileRange<ProfRange>::value>** = nullptr> - ABSL_MUST_USE_RESULT ::testing::AssertionResult with_strict_profile( - ProfRange /*profile*/) { - ConformanceErrors test_result = - (ExpectRegularityImpl< - T, LogicalProfileOfT<ProfRange>, MinProfileOfT<ProfRange>, - MaxProfileOfT<ProfRange>>)(absl::move(ordered_vals)); - - return ExpectSuccess ? test_result.assertionResult() - : test_result.expectFailedTests(expected_failed_tests); - } - - // Execute the tests for the captured set of values, loosely matching a range - // of expected profiles (loose in that an interface is allowed to be more - // refined that a profile suggests, such as a type having a noexcept copy - // constructor when all that is required is that the copy constructor exists). - template <class Prof, absl::enable_if_t<IsProfile<Prof>::value>** = nullptr> - ABSL_MUST_USE_RESULT ::testing::AssertionResult with_loose_profile( - Prof /*profile*/) { - ConformanceErrors test_result = - (ExpectRegularityImpl< - T, Prof, Prof, - CombineProfiles<TriviallyCompleteProfile, - NothrowComparableProfile>>)(absl:: - move(ordered_vals)); - - return ExpectSuccess ? test_result.assertionResult() - : test_result.expectFailedTests(expected_failed_tests); - } - - OrderedEquivalenceClasses<EqClasses...> ordered_vals; - std::set<std::string> expected_failed_tests; -}; - -template <class T> -using ExpectConformanceOfType = ExpectConformanceOf</*ExpectSuccess=*/true, T>; - -template <class T> -using ExpectNonconformanceOfType = - ExpectConformanceOf</*ExpectSuccess=*/false, T>; - -struct EquivalenceClassMaker { - // TODO(calabrese) Constrain to callable - template <class Fun> - static GeneratorType<Fun> initializer(GeneratorType<Fun> fun) { - return fun; - } -}; - -// A top-level macro that begins the builder pattern. -// -// The argument here takes the datatype to be tested. -#define ABSL_INTERNAL_ASSERT_CONFORMANCE_OF(...) \ - GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if ABSL_INTERNAL_LPAREN \ - const ::testing::AssertionResult gtest_ar = \ - ABSL_INTERNAL_LPAREN ::absl::types_internal::ExpectConformanceOfType< \ - __VA_ARGS__>() - -// Akin to ASSERT_CONFORMANCE_OF except that it expects failure and tries to -// match text. -#define ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(...) \ - GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if ABSL_INTERNAL_LPAREN \ - const ::testing::AssertionResult gtest_ar = \ - ABSL_INTERNAL_LPAREN ::absl::types_internal::ExpectNonconformanceOfType< \ - __VA_ARGS__>() - -//////////////////////////////////////////////////////////////////////////////// -// NOTE: The following macros look like they are recursive, but are not (macros -// cannot recurse). These actually refer to member functions of the same name. -// This is done intentionally so that a user cannot accidentally invoke a -// member function of the conformance-testing suite without going through the -// macro. -//////////////////////////////////////////////////////////////////////////////// - -// Specify expected test failures as comma-separated strings. -#define DUE_TO(...) due_to(__VA_ARGS__) - -// Specify a value to be tested. -// -// Note: Internally, this takes an expression and turns it into the return value -// of lambda that captures no data. The expression is stringized during -// preprocessing so that it can be used in error reports. -#define INITIALIZER(...) \ - initializer(::absl::types_internal::Generator( \ - [] { return __VA_ARGS__; }, ABSL_INTERNAL_STRINGIZE(__VA_ARGS__))) - -// Specify a value to be tested. -// -// Note: Internally, this takes an expression and turns it into the return value -// of lambda that captures data by reference. The expression is stringized -// during preprocessing so that it can be used in error reports. -#define STATEFUL_INITIALIZER(...) \ - stateful_initializer(::absl::types_internal::Generator( \ - [&] { return __VA_ARGS__; }, ABSL_INTERNAL_STRINGIZE(__VA_ARGS__))) - -// Used in the builder-pattern. -// -// Takes a series of INITIALIZER and/or STATEFUL_INITIALIZER invocations and -// forwards them along to be tested, grouping them such that the testing suite -// knows that they are supposed to represent the same logical value (the values -// compare the same, hash the same, etc.). -#define EQUIVALENCE_CLASS(...) \ - equivalence_class(ABSL_INTERNAL_TRANSFORM_ARGS( \ - ABSL_INTERNAL_PREPEND_EQ_MAKER, __VA_ARGS__)) - -// An invocation of this or WITH_STRICT_PROFILE must end the builder-pattern. -// It takes a Profile as its argument. -// -// This executes the tests and allows types that are "more referined" than the -// profile specifies, but not less. For instance, if the Profile specifies -// noexcept copy-constructiblity, the test will fail if the copy-constructor is -// not noexcept, however, it will succeed if the copy constructor is trivial. -// -// This is useful for testing that a type meets some minimum set of -// requirements. -#define WITH_LOOSE_PROFILE(...) \ - with_loose_profile( \ - ::absl::types_internal::MakeLooseProfileRangeT<__VA_ARGS__>()) \ - ABSL_INTERNAL_RPAREN ABSL_INTERNAL_RPAREN; \ - else GTEST_FATAL_FAILURE_(gtest_ar.failure_message()) // NOLINT - -// An invocation of this or WITH_STRICT_PROFILE must end the builder-pattern. -// It takes a Domain and a Profile as its arguments. -// -// This executes the tests and disallows types that differ at all from the -// properties of the Profile. For instance, if the Profile specifies noexcept -// copy-constructiblity, the test will fail if the copy constructor is trivial. -// -// This is useful for testing that a type does not do anything more than a -// specification requires, such as to minimize things like Hyrum's Law, or more -// commonly, to prevent a type from being "accidentally" copy-constructible in -// a way that may produce incorrect results, simply because the user forget to -// delete that operation. -#define WITH_STRICT_PROFILE(...) \ - with_strict_profile( \ - ::absl::types_internal::MakeStrictProfileRangeT<__VA_ARGS__>()) \ - ABSL_INTERNAL_RPAREN ABSL_INTERNAL_RPAREN; \ - else GTEST_FATAL_FAILURE_(gtest_ar.failure_message()) // NOLINT - -// Internal macro that is used in the internals of the EDSL when forming -// equivalence classes. -#define ABSL_INTERNAL_PREPEND_EQ_MAKER(arg) \ - ::absl::types_internal::EquivalenceClassMaker().arg - -} // namespace types_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_H_ diff --git a/third_party/abseil_cpp/absl/types/internal/conformance_testing_helpers.h b/third_party/abseil_cpp/absl/types/internal/conformance_testing_helpers.h deleted file mode 100644 index 00775f960c36..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/conformance_testing_helpers.h +++ /dev/null @@ -1,391 +0,0 @@ -// Copyright 2019 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_HELPERS_H_ -#define ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_HELPERS_H_ - -// Checks to determine whether or not we can use abi::__cxa_demangle -#if (defined(__ANDROID__) || defined(ANDROID)) && !defined(OS_ANDROID) -#define ABSL_INTERNAL_OS_ANDROID -#endif - -// We support certain compilers only. See demangle.h for details. -#if defined(OS_ANDROID) && (defined(__i386__) || defined(__x86_64__)) -#define ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE 0 -#elif (__GNUC__ >= 4 || (__GNUC__ >= 3 && __GNUC_MINOR__ >= 4)) && \ - !defined(__mips__) -#define ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE 1 -#elif defined(__clang__) && !defined(_MSC_VER) -#define ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE 1 -#else -#define ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE 0 -#endif - -#include <tuple> -#include <type_traits> -#include <utility> - -#include "absl/meta/type_traits.h" -#include "absl/strings/string_view.h" -#include "absl/utility/utility.h" - -#if ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE -#include <cxxabi.h> - -#include <cstdlib> -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace types_internal { - -// Return a readable name for type T. -template <class T> -absl::string_view NameOfImpl() { -// TODO(calabrese) Investigate using debugging:internal_demangle as a fallback. -#if ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE - int status = 0; - char* demangled_name = nullptr; - - demangled_name = - abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &status); - - if (status == 0 && demangled_name != nullptr) { - return demangled_name; - } else { - return typeid(T).name(); - } -#else - return typeid(T).name(); -#endif - // NOTE: We intentionally leak demangled_name so that it remains valid - // throughout the remainder of the program. -} - -// Given a type, returns as nice of a type name as we can produce (demangled). -// -// Note: This currently strips cv-qualifiers and references, but that is okay -// because we only use this internally with unqualified object types. -template <class T> -std::string NameOf() { - static const absl::string_view result = NameOfImpl<T>(); - return std::string(result); -} - -//////////////////////////////////////////////////////////////////////////////// -// -// Metafunction to check if a type is callable with no explicit arguments -template <class Fun, class /*Enabler*/ = void> -struct IsNullaryCallableImpl : std::false_type {}; - -template <class Fun> -struct IsNullaryCallableImpl< - Fun, absl::void_t<decltype(std::declval<const Fun&>()())>> - : std::true_type { - using result_type = decltype(std::declval<const Fun&>()()); - - template <class ValueType> - using for_type = std::is_same<ValueType, result_type>; - - using void_if_true = void; -}; - -template <class Fun> -struct IsNullaryCallable : IsNullaryCallableImpl<Fun> {}; -// -//////////////////////////////////////////////////////////////////////////////// - -// A type that contains a function object that returns an instance of a type -// that is undergoing conformance testing. This function is required to always -// return the same value upon invocation. -template <class Fun> -struct GeneratorType; - -// A type that contains a tuple of GeneratorType<Fun> where each Fun has the -// same return type. The result of each of the different generators should all -// be equal values, though the underlying object representation may differ (such -// as if one returns 0.0 and another return -0.0, or if one returns an empty -// vector and another returns an empty vector with a different capacity. -template <class... Funs> -struct EquivalenceClassType; - -//////////////////////////////////////////////////////////////////////////////// -// -// A metafunction to check if a type is a specialization of EquivalenceClassType -template <class T> -struct IsEquivalenceClass : std::false_type {}; - -template <> -struct IsEquivalenceClass<EquivalenceClassType<>> : std::true_type { - using self = IsEquivalenceClass; - - // A metafunction to check if this EquivalenceClassType is a valid - // EquivalenceClassType for a type `ValueType` that is undergoing testing - template <class ValueType> - using for_type = std::true_type; -}; - -template <class Head, class... Tail> -struct IsEquivalenceClass<EquivalenceClassType<Head, Tail...>> - : std::true_type { - using self = IsEquivalenceClass; - - // The type undergoing conformance testing that this EquivalenceClass - // corresponds to - using result_type = typename IsNullaryCallable<Head>::result_type; - - // A metafunction to check if this EquivalenceClassType is a valid - // EquivalenceClassType for a type `ValueType` that is undergoing testing - template <class ValueType> - using for_type = std::is_same<ValueType, result_type>; -}; -// -//////////////////////////////////////////////////////////////////////////////// - -// A type that contains an ordered series of EquivalenceClassTypes, where the -// the function object of each underlying GeneratorType has the same return type -// -// These equivalence classes are required to be in a logical ascending order -// that is consistent with comparison operators that are defined for the return -// type of each GeneratorType, if any. -template <class... EqClasses> -struct OrderedEquivalenceClasses; - -//////////////////////////////////////////////////////////////////////////////// -// -// A metafunction to determine the return type of the function object contained -// in a GeneratorType specialization. -template <class T> -struct ResultOfGenerator {}; - -template <class Fun> -struct ResultOfGenerator<GeneratorType<Fun>> { - using type = decltype(std::declval<const Fun&>()()); -}; - -template <class Fun> -using ResultOfGeneratorT = typename ResultOfGenerator<GeneratorType<Fun>>::type; -// -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -// -// A metafunction that yields true iff each of Funs is a GeneratorType -// specialization and they all contain functions with the same return type -template <class /*Enabler*/, class... Funs> -struct AreGeneratorsWithTheSameReturnTypeImpl : std::false_type {}; - -template <> -struct AreGeneratorsWithTheSameReturnTypeImpl<void> : std::true_type {}; - -template <class Head, class... Tail> -struct AreGeneratorsWithTheSameReturnTypeImpl< - typename std::enable_if<absl::conjunction<std::is_same< - ResultOfGeneratorT<Head>, ResultOfGeneratorT<Tail>>...>::value>::type, - Head, Tail...> : std::true_type {}; - -template <class... Funs> -struct AreGeneratorsWithTheSameReturnType - : AreGeneratorsWithTheSameReturnTypeImpl<void, Funs...>::type {}; -// -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -// -// A metafunction that yields true iff each of Funs is an EquivalenceClassType -// specialization and they all contain GeneratorType specializations that have -// the same return type -template <class... EqClasses> -struct AreEquivalenceClassesOfTheSameType { - static_assert(sizeof...(EqClasses) != sizeof...(EqClasses), ""); -}; - -template <> -struct AreEquivalenceClassesOfTheSameType<> : std::true_type { - using self = AreEquivalenceClassesOfTheSameType; - - // Metafunction to check that a type is the same as all of the equivalence - // classes, if any. - // Note: In this specialization there are no equivalence classes, so the - // value type is always compatible. - template <class /*ValueType*/> - using for_type = std::true_type; -}; - -template <class... Funs> -struct AreEquivalenceClassesOfTheSameType<EquivalenceClassType<Funs...>> - : std::true_type { - using self = AreEquivalenceClassesOfTheSameType; - - // Metafunction to check that a type is the same as all of the equivalence - // classes, if any. - template <class ValueType> - using for_type = typename IsEquivalenceClass< - EquivalenceClassType<Funs...>>::template for_type<ValueType>; -}; - -template <class... TailEqClasses> -struct AreEquivalenceClassesOfTheSameType< - EquivalenceClassType<>, EquivalenceClassType<>, TailEqClasses...> - : AreEquivalenceClassesOfTheSameType<TailEqClasses...>::self {}; - -template <class HeadNextFun, class... TailNextFuns, class... TailEqClasses> -struct AreEquivalenceClassesOfTheSameType< - EquivalenceClassType<>, EquivalenceClassType<HeadNextFun, TailNextFuns...>, - TailEqClasses...> - : AreEquivalenceClassesOfTheSameType< - EquivalenceClassType<HeadNextFun, TailNextFuns...>, - TailEqClasses...>::self {}; - -template <class HeadHeadFun, class... TailHeadFuns, class... TailEqClasses> -struct AreEquivalenceClassesOfTheSameType< - EquivalenceClassType<HeadHeadFun, TailHeadFuns...>, EquivalenceClassType<>, - TailEqClasses...> - : AreEquivalenceClassesOfTheSameType< - EquivalenceClassType<HeadHeadFun, TailHeadFuns...>, - TailEqClasses...>::self {}; - -template <class HeadHeadFun, class... TailHeadFuns, class HeadNextFun, - class... TailNextFuns, class... TailEqClasses> -struct AreEquivalenceClassesOfTheSameType< - EquivalenceClassType<HeadHeadFun, TailHeadFuns...>, - EquivalenceClassType<HeadNextFun, TailNextFuns...>, TailEqClasses...> - : absl::conditional_t< - IsNullaryCallable<HeadNextFun>::template for_type< - typename IsNullaryCallable<HeadHeadFun>::result_type>::value, - AreEquivalenceClassesOfTheSameType< - EquivalenceClassType<HeadHeadFun, TailHeadFuns...>, - TailEqClasses...>, - std::false_type> {}; -// -//////////////////////////////////////////////////////////////////////////////// - -// Execute a function for each passed-in parameter. -template <class Fun, class... Cases> -void ForEachParameter(const Fun& fun, const Cases&... cases) { - const std::initializer_list<bool> results = { - (static_cast<void>(fun(cases)), true)...}; - - (void)results; -} - -// Execute a function on each passed-in parameter (using a bound function). -template <class Fun> -struct ForEachParameterFun { - template <class... T> - void operator()(const T&... cases) const { - (ForEachParameter)(fun, cases...); - } - - Fun fun; -}; - -// Execute a function on each element of a tuple. -template <class Fun, class Tup> -void ForEachTupleElement(const Fun& fun, const Tup& tup) { - absl::apply(ForEachParameterFun<Fun>{fun}, tup); -} - -//////////////////////////////////////////////////////////////////////////////// -// -// Execute a function for each combination of two elements of a tuple, including -// combinations of an element with itself. -template <class Fun, class... T> -struct ForEveryTwoImpl { - template <class Lhs> - struct WithBoundLhs { - template <class Rhs> - void operator()(const Rhs& rhs) const { - fun(lhs, rhs); - } - - Fun fun; - Lhs lhs; - }; - - template <class Lhs> - void operator()(const Lhs& lhs) const { - (ForEachTupleElement)(WithBoundLhs<Lhs>{fun, lhs}, args); - } - - Fun fun; - std::tuple<T...> args; -}; - -template <class Fun, class... T> -void ForEveryTwo(const Fun& fun, std::tuple<T...> args) { - (ForEachTupleElement)(ForEveryTwoImpl<Fun, T...>{fun, args}, args); -} -// -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -// -// Insert all values into an associative container -template<class Container> -void InsertEach(Container* cont) { -} - -template<class Container, class H, class... T> -void InsertEach(Container* cont, H&& head, T&&... tail) { - cont->insert(head); - (InsertEach)(cont, tail...); -} -// -//////////////////////////////////////////////////////////////////////////////// -// A template with a nested "Invoke" static-member-function that executes a -// passed-in Callable when `Condition` is true, otherwise it ignores the -// Callable. This is useful for executing a function object with a condition -// that corresponds to whether or not the Callable can be safely instantiated. -// It has some overlapping uses with C++17 `if constexpr`. -template <bool Condition> -struct If; - -template <> -struct If</*Condition =*/false> { - template <class Fun, class... P> - static void Invoke(const Fun& /*fun*/, P&&... /*args*/) {} -}; - -template <> -struct If</*Condition =*/true> { - template <class Fun, class... P> - static void Invoke(const Fun& fun, P&&... args) { - // TODO(calabrese) Use std::invoke equivalent instead of function-call. - fun(absl::forward<P>(args)...); - } -}; - -// -// ABSL_INTERNAL_STRINGIZE(...) -// -// This variadic macro transforms its arguments into a c-string literal after -// expansion. -// -// Example: -// -// ABSL_INTERNAL_STRINGIZE(std::array<int, 10>) -// -// Results in: -// -// "std::array<int, 10>" -#define ABSL_INTERNAL_STRINGIZE(...) ABSL_INTERNAL_STRINGIZE_IMPL((__VA_ARGS__)) -#define ABSL_INTERNAL_STRINGIZE_IMPL(arg) ABSL_INTERNAL_STRINGIZE_IMPL2 arg -#define ABSL_INTERNAL_STRINGIZE_IMPL2(...) #__VA_ARGS__ - -} // namespace types_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_HELPERS_H_ diff --git a/third_party/abseil_cpp/absl/types/internal/conformance_testing_test.cc b/third_party/abseil_cpp/absl/types/internal/conformance_testing_test.cc deleted file mode 100644 index cf262fa6c222..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/conformance_testing_test.cc +++ /dev/null @@ -1,1556 +0,0 @@ -// Copyright 2019 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "absl/types/internal/conformance_testing.h" - -#include <new> -#include <type_traits> -#include <utility> - -#include "gtest/gtest.h" -#include "absl/meta/type_traits.h" -#include "absl/types/internal/conformance_aliases.h" -#include "absl/types/internal/conformance_profile.h" - -namespace { - -namespace ti = absl::types_internal; - -template <class T> -using DefaultConstructibleWithNewImpl = decltype(::new (std::nothrow) T); - -template <class T> -using DefaultConstructibleWithNew = - absl::type_traits_internal::is_detected<DefaultConstructibleWithNewImpl, T>; - -template <class T> -using MoveConstructibleWithNewImpl = - decltype(::new (std::nothrow) T(std::declval<T>())); - -template <class T> -using MoveConstructibleWithNew = - absl::type_traits_internal::is_detected<MoveConstructibleWithNewImpl, T>; - -template <class T> -using CopyConstructibleWithNewImpl = - decltype(::new (std::nothrow) T(std::declval<const T&>())); - -template <class T> -using CopyConstructibleWithNew = - absl::type_traits_internal::is_detected<CopyConstructibleWithNewImpl, T>; - -template <class T, - class Result = - std::integral_constant<bool, noexcept(::new (std::nothrow) T)>> -using NothrowDefaultConstructibleWithNewImpl = - typename std::enable_if<Result::value>::type; - -template <class T> -using NothrowDefaultConstructibleWithNew = - absl::type_traits_internal::is_detected< - NothrowDefaultConstructibleWithNewImpl, T>; - -template <class T, - class Result = std::integral_constant< - bool, noexcept(::new (std::nothrow) T(std::declval<T>()))>> -using NothrowMoveConstructibleWithNewImpl = - typename std::enable_if<Result::value>::type; - -template <class T> -using NothrowMoveConstructibleWithNew = - absl::type_traits_internal::is_detected<NothrowMoveConstructibleWithNewImpl, - T>; - -template <class T, - class Result = std::integral_constant< - bool, noexcept(::new (std::nothrow) T(std::declval<const T&>()))>> -using NothrowCopyConstructibleWithNewImpl = - typename std::enable_if<Result::value>::type; - -template <class T> -using NothrowCopyConstructibleWithNew = - absl::type_traits_internal::is_detected<NothrowCopyConstructibleWithNewImpl, - T>; - -// NOTE: ?: is used to verify contextually-convertible to bool and not simply -// implicit or explicit convertibility. -#define ABSL_INTERNAL_COMPARISON_OP_EXPR(op) \ - ((std::declval<const T&>() op std::declval<const T&>()) ? true : true) - -#define ABSL_INTERNAL_COMPARISON_OP_TRAIT(name, op) \ - template <class T> \ - using name##Impl = decltype(ABSL_INTERNAL_COMPARISON_OP_EXPR(op)); \ - \ - template <class T> \ - using name = absl::type_traits_internal::is_detected<name##Impl, T>; \ - \ - template <class T, \ - class Result = std::integral_constant< \ - bool, noexcept(ABSL_INTERNAL_COMPARISON_OP_EXPR(op))>> \ - using Nothrow##name##Impl = typename std::enable_if<Result::value>::type; \ - \ - template <class T> \ - using Nothrow##name = \ - absl::type_traits_internal::is_detected<Nothrow##name##Impl, T> - -ABSL_INTERNAL_COMPARISON_OP_TRAIT(EqualityComparable, ==); -ABSL_INTERNAL_COMPARISON_OP_TRAIT(InequalityComparable, !=); -ABSL_INTERNAL_COMPARISON_OP_TRAIT(LessThanComparable, <); -ABSL_INTERNAL_COMPARISON_OP_TRAIT(LessEqualComparable, <=); -ABSL_INTERNAL_COMPARISON_OP_TRAIT(GreaterEqualComparable, >=); -ABSL_INTERNAL_COMPARISON_OP_TRAIT(GreaterThanComparable, >); - -#undef ABSL_INTERNAL_COMPARISON_OP_TRAIT - -template <class T> -class ProfileTest : public ::testing::Test {}; - -TYPED_TEST_SUITE_P(ProfileTest); - -TYPED_TEST_P(ProfileTest, HasAppropriateConstructionProperties) { - using profile = typename TypeParam::profile; - using arch = typename TypeParam::arch; - using expected_profile = typename TypeParam::expected_profile; - - using props = ti::PropertiesOfT<profile>; - using arch_props = ti::PropertiesOfArchetypeT<arch>; - using expected_props = ti::PropertiesOfT<expected_profile>; - - // Make sure all of the properties are as expected. - // There are seemingly redundant tests here to make it easier to diagnose - // the specifics of the failure if something were to go wrong. - EXPECT_TRUE((std::is_same<props, arch_props>::value)); - EXPECT_TRUE((std::is_same<props, expected_props>::value)); - EXPECT_TRUE((std::is_same<arch_props, expected_props>::value)); - - EXPECT_EQ(props::default_constructible_support, - expected_props::default_constructible_support); - - EXPECT_EQ(props::move_constructible_support, - expected_props::move_constructible_support); - - EXPECT_EQ(props::copy_constructible_support, - expected_props::copy_constructible_support); - - EXPECT_EQ(props::destructible_support, expected_props::destructible_support); - - // Avoid additional error message noise when profile and archetype match with - // each other but were not what was expected. - if (!std::is_same<props, arch_props>::value) { - EXPECT_EQ(arch_props::default_constructible_support, - expected_props::default_constructible_support); - - EXPECT_EQ(arch_props::move_constructible_support, - expected_props::move_constructible_support); - - EXPECT_EQ(arch_props::copy_constructible_support, - expected_props::copy_constructible_support); - - EXPECT_EQ(arch_props::destructible_support, - expected_props::destructible_support); - } - - ////////////////////////////////////////////////////////////////////////////// - // Default constructor checks // - ////////////////////////////////////////////////////////////////////////////// - EXPECT_EQ(props::default_constructible_support, - expected_props::default_constructible_support); - - switch (expected_props::default_constructible_support) { - case ti::default_constructible::maybe: - EXPECT_FALSE(DefaultConstructibleWithNew<arch>::value); - EXPECT_FALSE(NothrowDefaultConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_FALSE(std::is_default_constructible<arch>::value); - EXPECT_FALSE(std::is_nothrow_default_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_default_constructible<arch>::value); - } - break; - case ti::default_constructible::yes: - EXPECT_TRUE(DefaultConstructibleWithNew<arch>::value); - EXPECT_FALSE(NothrowDefaultConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_default_constructible<arch>::value); - EXPECT_FALSE(std::is_nothrow_default_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_default_constructible<arch>::value); - } - break; - case ti::default_constructible::nothrow: - EXPECT_TRUE(DefaultConstructibleWithNew<arch>::value); - EXPECT_TRUE(NothrowDefaultConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_default_constructible<arch>::value); - EXPECT_TRUE(std::is_nothrow_default_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_default_constructible<arch>::value); - - // Constructor traits also check the destructor. - if (std::is_nothrow_destructible<arch>::value) { - EXPECT_TRUE(std::is_nothrow_default_constructible<arch>::value); - } - } - break; - case ti::default_constructible::trivial: - EXPECT_TRUE(DefaultConstructibleWithNew<arch>::value); - EXPECT_TRUE(NothrowDefaultConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_default_constructible<arch>::value); - EXPECT_TRUE(std::is_nothrow_default_constructible<arch>::value); - - // Constructor triviality traits require trivially destructible types. - if (absl::is_trivially_destructible<arch>::value) { - EXPECT_TRUE(absl::is_trivially_default_constructible<arch>::value); - } - } - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Move constructor checks // - ////////////////////////////////////////////////////////////////////////////// - EXPECT_EQ(props::move_constructible_support, - expected_props::move_constructible_support); - - switch (expected_props::move_constructible_support) { - case ti::move_constructible::maybe: - EXPECT_FALSE(MoveConstructibleWithNew<arch>::value); - EXPECT_FALSE(NothrowMoveConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_FALSE(std::is_move_constructible<arch>::value); - EXPECT_FALSE(std::is_nothrow_move_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_move_constructible<arch>::value); - } - break; - case ti::move_constructible::yes: - EXPECT_TRUE(MoveConstructibleWithNew<arch>::value); - EXPECT_FALSE(NothrowMoveConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_move_constructible<arch>::value); - EXPECT_FALSE(std::is_nothrow_move_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_move_constructible<arch>::value); - } - break; - case ti::move_constructible::nothrow: - EXPECT_TRUE(MoveConstructibleWithNew<arch>::value); - EXPECT_TRUE(NothrowMoveConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_move_constructible<arch>::value); - EXPECT_TRUE(std::is_nothrow_move_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_move_constructible<arch>::value); - - // Constructor traits also check the destructor. - if (std::is_nothrow_destructible<arch>::value) { - EXPECT_TRUE(std::is_nothrow_move_constructible<arch>::value); - } - } - break; - case ti::move_constructible::trivial: - EXPECT_TRUE(MoveConstructibleWithNew<arch>::value); - EXPECT_TRUE(NothrowMoveConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_move_constructible<arch>::value); - EXPECT_TRUE(std::is_nothrow_move_constructible<arch>::value); - - // Constructor triviality traits require trivially destructible types. - if (absl::is_trivially_destructible<arch>::value) { - EXPECT_TRUE(absl::is_trivially_move_constructible<arch>::value); - } - } - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Copy constructor checks // - ////////////////////////////////////////////////////////////////////////////// - EXPECT_EQ(props::copy_constructible_support, - expected_props::copy_constructible_support); - - switch (expected_props::copy_constructible_support) { - case ti::copy_constructible::maybe: - EXPECT_FALSE(CopyConstructibleWithNew<arch>::value); - EXPECT_FALSE(NothrowCopyConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_FALSE(std::is_copy_constructible<arch>::value); - EXPECT_FALSE(std::is_nothrow_copy_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_copy_constructible<arch>::value); - } - break; - case ti::copy_constructible::yes: - EXPECT_TRUE(CopyConstructibleWithNew<arch>::value); - EXPECT_FALSE(NothrowCopyConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_copy_constructible<arch>::value); - EXPECT_FALSE(std::is_nothrow_copy_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_copy_constructible<arch>::value); - } - break; - case ti::copy_constructible::nothrow: - EXPECT_TRUE(CopyConstructibleWithNew<arch>::value); - EXPECT_TRUE(NothrowCopyConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_copy_constructible<arch>::value); - EXPECT_TRUE(std::is_nothrow_copy_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_copy_constructible<arch>::value); - - // Constructor traits also check the destructor. - if (std::is_nothrow_destructible<arch>::value) { - EXPECT_TRUE(std::is_nothrow_copy_constructible<arch>::value); - } - } - break; - case ti::copy_constructible::trivial: - EXPECT_TRUE(CopyConstructibleWithNew<arch>::value); - EXPECT_TRUE(NothrowCopyConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_copy_constructible<arch>::value); - EXPECT_TRUE(std::is_nothrow_copy_constructible<arch>::value); - - // Constructor triviality traits require trivially destructible types. - if (absl::is_trivially_destructible<arch>::value) { - EXPECT_TRUE(absl::is_trivially_copy_constructible<arch>::value); - } - } - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Destructible checks // - ////////////////////////////////////////////////////////////////////////////// - EXPECT_EQ(props::destructible_support, expected_props::destructible_support); - - switch (expected_props::destructible_support) { - case ti::destructible::maybe: - EXPECT_FALSE(std::is_destructible<arch>::value); - EXPECT_FALSE(std::is_nothrow_destructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_destructible<arch>::value); - break; - case ti::destructible::yes: - EXPECT_TRUE(std::is_destructible<arch>::value); - EXPECT_FALSE(std::is_nothrow_destructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_destructible<arch>::value); - break; - case ti::destructible::nothrow: - EXPECT_TRUE(std::is_destructible<arch>::value); - EXPECT_TRUE(std::is_nothrow_destructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_destructible<arch>::value); - break; - case ti::destructible::trivial: - EXPECT_TRUE(std::is_destructible<arch>::value); - EXPECT_TRUE(std::is_nothrow_destructible<arch>::value); - EXPECT_TRUE(absl::is_trivially_destructible<arch>::value); - break; - } -} - -TYPED_TEST_P(ProfileTest, HasAppropriateAssignmentProperties) { - using profile = typename TypeParam::profile; - using arch = typename TypeParam::arch; - using expected_profile = typename TypeParam::expected_profile; - - using props = ti::PropertiesOfT<profile>; - using arch_props = ti::PropertiesOfArchetypeT<arch>; - using expected_props = ti::PropertiesOfT<expected_profile>; - - // Make sure all of the properties are as expected. - // There are seemingly redundant tests here to make it easier to diagnose - // the specifics of the failure if something were to go wrong. - EXPECT_TRUE((std::is_same<props, arch_props>::value)); - EXPECT_TRUE((std::is_same<props, expected_props>::value)); - EXPECT_TRUE((std::is_same<arch_props, expected_props>::value)); - - EXPECT_EQ(props::move_assignable_support, - expected_props::move_assignable_support); - - EXPECT_EQ(props::copy_assignable_support, - expected_props::copy_assignable_support); - - // Avoid additional error message noise when profile and archetype match with - // each other but were not what was expected. - if (!std::is_same<props, arch_props>::value) { - EXPECT_EQ(arch_props::move_assignable_support, - expected_props::move_assignable_support); - - EXPECT_EQ(arch_props::copy_assignable_support, - expected_props::copy_assignable_support); - } - - ////////////////////////////////////////////////////////////////////////////// - // Move assignment checks // - ////////////////////////////////////////////////////////////////////////////// - EXPECT_EQ(props::move_assignable_support, - expected_props::move_assignable_support); - - switch (expected_props::move_assignable_support) { - case ti::move_assignable::maybe: - EXPECT_FALSE(std::is_move_assignable<arch>::value); - EXPECT_FALSE(std::is_nothrow_move_assignable<arch>::value); - EXPECT_FALSE(absl::is_trivially_move_assignable<arch>::value); - break; - case ti::move_assignable::yes: - EXPECT_TRUE(std::is_move_assignable<arch>::value); - EXPECT_FALSE(std::is_nothrow_move_assignable<arch>::value); - EXPECT_FALSE(absl::is_trivially_move_assignable<arch>::value); - break; - case ti::move_assignable::nothrow: - EXPECT_TRUE(std::is_move_assignable<arch>::value); - EXPECT_TRUE(std::is_nothrow_move_assignable<arch>::value); - EXPECT_FALSE(absl::is_trivially_move_assignable<arch>::value); - break; - case ti::move_assignable::trivial: - EXPECT_TRUE(std::is_move_assignable<arch>::value); - EXPECT_TRUE(std::is_nothrow_move_assignable<arch>::value); - EXPECT_TRUE(absl::is_trivially_move_assignable<arch>::value); - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Copy assignment checks // - ////////////////////////////////////////////////////////////////////////////// - EXPECT_EQ(props::copy_assignable_support, - expected_props::copy_assignable_support); - - switch (expected_props::copy_assignable_support) { - case ti::copy_assignable::maybe: - EXPECT_FALSE(std::is_copy_assignable<arch>::value); - EXPECT_FALSE(std::is_nothrow_copy_assignable<arch>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<arch>::value); - break; - case ti::copy_assignable::yes: - EXPECT_TRUE(std::is_copy_assignable<arch>::value); - EXPECT_FALSE(std::is_nothrow_copy_assignable<arch>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<arch>::value); - break; - case ti::copy_assignable::nothrow: - EXPECT_TRUE(std::is_copy_assignable<arch>::value); - EXPECT_TRUE(std::is_nothrow_copy_assignable<arch>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<arch>::value); - break; - case ti::copy_assignable::trivial: - EXPECT_TRUE(std::is_copy_assignable<arch>::value); - EXPECT_TRUE(std::is_nothrow_copy_assignable<arch>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<arch>::value); - break; - } -} - -TYPED_TEST_P(ProfileTest, HasAppropriateComparisonProperties) { - using profile = typename TypeParam::profile; - using arch = typename TypeParam::arch; - using expected_profile = typename TypeParam::expected_profile; - - using props = ti::PropertiesOfT<profile>; - using arch_props = ti::PropertiesOfArchetypeT<arch>; - using expected_props = ti::PropertiesOfT<expected_profile>; - - // Make sure all of the properties are as expected. - // There are seemingly redundant tests here to make it easier to diagnose - // the specifics of the failure if something were to go wrong. - EXPECT_TRUE((std::is_same<props, arch_props>::value)); - EXPECT_TRUE((std::is_same<props, expected_props>::value)); - EXPECT_TRUE((std::is_same<arch_props, expected_props>::value)); - - EXPECT_EQ(props::equality_comparable_support, - expected_props::equality_comparable_support); - - EXPECT_EQ(props::inequality_comparable_support, - expected_props::inequality_comparable_support); - - EXPECT_EQ(props::less_than_comparable_support, - expected_props::less_than_comparable_support); - - EXPECT_EQ(props::less_equal_comparable_support, - expected_props::less_equal_comparable_support); - - EXPECT_EQ(props::greater_equal_comparable_support, - expected_props::greater_equal_comparable_support); - - EXPECT_EQ(props::greater_than_comparable_support, - expected_props::greater_than_comparable_support); - - // Avoid additional error message noise when profile and archetype match with - // each other but were not what was expected. - if (!std::is_same<props, arch_props>::value) { - EXPECT_EQ(arch_props::equality_comparable_support, - expected_props::equality_comparable_support); - - EXPECT_EQ(arch_props::inequality_comparable_support, - expected_props::inequality_comparable_support); - - EXPECT_EQ(arch_props::less_than_comparable_support, - expected_props::less_than_comparable_support); - - EXPECT_EQ(arch_props::less_equal_comparable_support, - expected_props::less_equal_comparable_support); - - EXPECT_EQ(arch_props::greater_equal_comparable_support, - expected_props::greater_equal_comparable_support); - - EXPECT_EQ(arch_props::greater_than_comparable_support, - expected_props::greater_than_comparable_support); - } - - ////////////////////////////////////////////////////////////////////////////// - // Equality comparable checks // - ////////////////////////////////////////////////////////////////////////////// - switch (expected_props::equality_comparable_support) { - case ti::equality_comparable::maybe: - EXPECT_FALSE(EqualityComparable<arch>::value); - EXPECT_FALSE(NothrowEqualityComparable<arch>::value); - break; - case ti::equality_comparable::yes: - EXPECT_TRUE(EqualityComparable<arch>::value); - EXPECT_FALSE(NothrowEqualityComparable<arch>::value); - break; - case ti::equality_comparable::nothrow: - EXPECT_TRUE(EqualityComparable<arch>::value); - EXPECT_TRUE(NothrowEqualityComparable<arch>::value); - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Inequality comparable checks // - ////////////////////////////////////////////////////////////////////////////// - switch (expected_props::inequality_comparable_support) { - case ti::inequality_comparable::maybe: - EXPECT_FALSE(InequalityComparable<arch>::value); - EXPECT_FALSE(NothrowInequalityComparable<arch>::value); - break; - case ti::inequality_comparable::yes: - EXPECT_TRUE(InequalityComparable<arch>::value); - EXPECT_FALSE(NothrowInequalityComparable<arch>::value); - break; - case ti::inequality_comparable::nothrow: - EXPECT_TRUE(InequalityComparable<arch>::value); - EXPECT_TRUE(NothrowInequalityComparable<arch>::value); - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Less than comparable checks // - ////////////////////////////////////////////////////////////////////////////// - switch (expected_props::less_than_comparable_support) { - case ti::less_than_comparable::maybe: - EXPECT_FALSE(LessThanComparable<arch>::value); - EXPECT_FALSE(NothrowLessThanComparable<arch>::value); - break; - case ti::less_than_comparable::yes: - EXPECT_TRUE(LessThanComparable<arch>::value); - EXPECT_FALSE(NothrowLessThanComparable<arch>::value); - break; - case ti::less_than_comparable::nothrow: - EXPECT_TRUE(LessThanComparable<arch>::value); - EXPECT_TRUE(NothrowLessThanComparable<arch>::value); - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Less equal comparable checks // - ////////////////////////////////////////////////////////////////////////////// - switch (expected_props::less_equal_comparable_support) { - case ti::less_equal_comparable::maybe: - EXPECT_FALSE(LessEqualComparable<arch>::value); - EXPECT_FALSE(NothrowLessEqualComparable<arch>::value); - break; - case ti::less_equal_comparable::yes: - EXPECT_TRUE(LessEqualComparable<arch>::value); - EXPECT_FALSE(NothrowLessEqualComparable<arch>::value); - break; - case ti::less_equal_comparable::nothrow: - EXPECT_TRUE(LessEqualComparable<arch>::value); - EXPECT_TRUE(NothrowLessEqualComparable<arch>::value); - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Greater equal comparable checks // - ////////////////////////////////////////////////////////////////////////////// - switch (expected_props::greater_equal_comparable_support) { - case ti::greater_equal_comparable::maybe: - EXPECT_FALSE(GreaterEqualComparable<arch>::value); - EXPECT_FALSE(NothrowGreaterEqualComparable<arch>::value); - break; - case ti::greater_equal_comparable::yes: - EXPECT_TRUE(GreaterEqualComparable<arch>::value); - EXPECT_FALSE(NothrowGreaterEqualComparable<arch>::value); - break; - case ti::greater_equal_comparable::nothrow: - EXPECT_TRUE(GreaterEqualComparable<arch>::value); - EXPECT_TRUE(NothrowGreaterEqualComparable<arch>::value); - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Greater than comparable checks // - ////////////////////////////////////////////////////////////////////////////// - switch (expected_props::greater_than_comparable_support) { - case ti::greater_than_comparable::maybe: - EXPECT_FALSE(GreaterThanComparable<arch>::value); - EXPECT_FALSE(NothrowGreaterThanComparable<arch>::value); - break; - case ti::greater_than_comparable::yes: - EXPECT_TRUE(GreaterThanComparable<arch>::value); - EXPECT_FALSE(NothrowGreaterThanComparable<arch>::value); - break; - case ti::greater_than_comparable::nothrow: - EXPECT_TRUE(GreaterThanComparable<arch>::value); - EXPECT_TRUE(NothrowGreaterThanComparable<arch>::value); - break; - } -} - -TYPED_TEST_P(ProfileTest, HasAppropriateAuxilliaryProperties) { - using profile = typename TypeParam::profile; - using arch = typename TypeParam::arch; - using expected_profile = typename TypeParam::expected_profile; - - using props = ti::PropertiesOfT<profile>; - using arch_props = ti::PropertiesOfArchetypeT<arch>; - using expected_props = ti::PropertiesOfT<expected_profile>; - - // Make sure all of the properties are as expected. - // There are seemingly redundant tests here to make it easier to diagnose - // the specifics of the failure if something were to go wrong. - EXPECT_TRUE((std::is_same<props, arch_props>::value)); - EXPECT_TRUE((std::is_same<props, expected_props>::value)); - EXPECT_TRUE((std::is_same<arch_props, expected_props>::value)); - - EXPECT_EQ(props::swappable_support, expected_props::swappable_support); - - EXPECT_EQ(props::hashable_support, expected_props::hashable_support); - - // Avoid additional error message noise when profile and archetype match with - // each other but were not what was expected. - if (!std::is_same<props, arch_props>::value) { - EXPECT_EQ(arch_props::swappable_support, expected_props::swappable_support); - - EXPECT_EQ(arch_props::hashable_support, expected_props::hashable_support); - } - - ////////////////////////////////////////////////////////////////////////////// - // Swappable checks // - ////////////////////////////////////////////////////////////////////////////// - switch (expected_props::swappable_support) { - case ti::swappable::maybe: - EXPECT_FALSE(absl::type_traits_internal::IsSwappable<arch>::value); - EXPECT_FALSE(absl::type_traits_internal::IsNothrowSwappable<arch>::value); - break; - case ti::swappable::yes: - EXPECT_TRUE(absl::type_traits_internal::IsSwappable<arch>::value); - EXPECT_FALSE(absl::type_traits_internal::IsNothrowSwappable<arch>::value); - break; - case ti::swappable::nothrow: - EXPECT_TRUE(absl::type_traits_internal::IsSwappable<arch>::value); - EXPECT_TRUE(absl::type_traits_internal::IsNothrowSwappable<arch>::value); - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Hashable checks // - ////////////////////////////////////////////////////////////////////////////// - switch (expected_props::hashable_support) { - case ti::hashable::maybe: -#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ - EXPECT_FALSE(absl::type_traits_internal::IsHashable<arch>::value); -#endif // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ - break; - case ti::hashable::yes: - EXPECT_TRUE(absl::type_traits_internal::IsHashable<arch>::value); - break; - } -} - -REGISTER_TYPED_TEST_SUITE_P(ProfileTest, HasAppropriateConstructionProperties, - HasAppropriateAssignmentProperties, - HasAppropriateComparisonProperties, - HasAppropriateAuxilliaryProperties); - -template <class Profile, class Arch, class ExpectedProfile> -struct ProfileAndExpectation { - using profile = Profile; - using arch = Arch; - using expected_profile = ExpectedProfile; -}; - -using CoreProfilesToTest = ::testing::Types< - // The terminating case of combine (all properties are "maybe"). - ProfileAndExpectation<ti::CombineProfiles<>, - ti::Archetype<ti::CombineProfiles<>>, - ti::ConformanceProfile<>>, - - // Core default constructor profiles - ProfileAndExpectation< - ti::HasDefaultConstructorProfile, ti::HasDefaultConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::yes>>, - ProfileAndExpectation< - ti::HasNothrowDefaultConstructorProfile, - ti::HasNothrowDefaultConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::nothrow>>, - ProfileAndExpectation< - ti::HasTrivialDefaultConstructorProfile, - ti::HasTrivialDefaultConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::trivial>>, - - // Core move constructor profiles - ProfileAndExpectation< - ti::HasMoveConstructorProfile, ti::HasMoveConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::maybe, - ti::move_constructible::yes>>, - ProfileAndExpectation< - ti::HasNothrowMoveConstructorProfile, - ti::HasNothrowMoveConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::maybe, - ti::move_constructible::nothrow>>, - ProfileAndExpectation< - ti::HasTrivialMoveConstructorProfile, - ti::HasTrivialMoveConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::maybe, - ti::move_constructible::trivial>>, - - // Core copy constructor profiles - ProfileAndExpectation< - ti::HasCopyConstructorProfile, ti::HasCopyConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::maybe, - ti::move_constructible::maybe, - ti::copy_constructible::yes>>, - ProfileAndExpectation< - ti::HasNothrowCopyConstructorProfile, - ti::HasNothrowCopyConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::maybe, - ti::move_constructible::maybe, - ti::copy_constructible::nothrow>>, - ProfileAndExpectation< - ti::HasTrivialCopyConstructorProfile, - ti::HasTrivialCopyConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::maybe, - ti::move_constructible::maybe, - ti::copy_constructible::trivial>>, - - // Core move assignment profiles - ProfileAndExpectation< - ti::HasMoveAssignProfile, ti::HasMoveAssignArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::yes>>, - ProfileAndExpectation< - ti::HasNothrowMoveAssignProfile, ti::HasNothrowMoveAssignArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::nothrow>>, - ProfileAndExpectation< - ti::HasTrivialMoveAssignProfile, ti::HasTrivialMoveAssignArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::trivial>>, - - // Core copy assignment profiles - ProfileAndExpectation< - ti::HasCopyAssignProfile, ti::HasCopyAssignArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::yes>>, - ProfileAndExpectation< - ti::HasNothrowCopyAssignProfile, ti::HasNothrowCopyAssignArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::nothrow>>, - ProfileAndExpectation< - ti::HasTrivialCopyAssignProfile, ti::HasTrivialCopyAssignArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::trivial>>, - - // Core destructor profiles - ProfileAndExpectation< - ti::HasDestructorProfile, ti::HasDestructorArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::yes>>, - ProfileAndExpectation< - ti::HasNothrowDestructorProfile, ti::HasNothrowDestructorArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::nothrow>>, - ProfileAndExpectation< - ti::HasTrivialDestructorProfile, ti::HasTrivialDestructorArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::trivial>>, - - // Core equality comparable profiles - ProfileAndExpectation< - ti::HasEqualityProfile, ti::HasEqualityArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::yes>>, - ProfileAndExpectation< - ti::HasNothrowEqualityProfile, ti::HasNothrowEqualityArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::nothrow>>, - - // Core inequality comparable profiles - ProfileAndExpectation< - ti::HasInequalityProfile, ti::HasInequalityArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::yes>>, - ProfileAndExpectation< - ti::HasNothrowInequalityProfile, ti::HasNothrowInequalityArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, - ti::inequality_comparable::nothrow>>, - - // Core less than comparable profiles - ProfileAndExpectation< - ti::HasLessThanProfile, ti::HasLessThanArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::yes>>, - ProfileAndExpectation< - ti::HasNothrowLessThanProfile, ti::HasNothrowLessThanArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::nothrow>>, - - // Core less equal comparable profiles - ProfileAndExpectation< - ti::HasLessEqualProfile, ti::HasLessEqualArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::yes>>, - ProfileAndExpectation< - ti::HasNothrowLessEqualProfile, ti::HasNothrowLessEqualArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, - ti::less_equal_comparable::nothrow>>, - - // Core greater equal comparable profiles - ProfileAndExpectation< - ti::HasGreaterEqualProfile, ti::HasGreaterEqualArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::yes>>, - ProfileAndExpectation< - ti::HasNothrowGreaterEqualProfile, ti::HasNothrowGreaterEqualArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::nothrow>>, - - // Core greater than comparable profiles - ProfileAndExpectation< - ti::HasGreaterThanProfile, ti::HasGreaterThanArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::yes>>, - ProfileAndExpectation< - ti::HasNothrowGreaterThanProfile, ti::HasNothrowGreaterThanArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::nothrow>>, - - // Core swappable profiles - ProfileAndExpectation< - ti::HasSwapProfile, ti::HasSwapArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::maybe, ti::swappable::yes>>, - ProfileAndExpectation< - ti::HasNothrowSwapProfile, ti::HasNothrowSwapArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::maybe, ti::swappable::nothrow>>, - - // Core hashable profiles - ProfileAndExpectation< - ti::HasStdHashSpecializationProfile, - ti::HasStdHashSpecializationArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::maybe, ti::swappable::maybe, - ti::hashable::yes>>>; - -using CommonProfilesToTest = ::testing::Types< - // NothrowMoveConstructible - ProfileAndExpectation< - ti::NothrowMoveConstructibleProfile, - ti::NothrowMoveConstructibleArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::nothrow, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::nothrow>>, - - // CopyConstructible - ProfileAndExpectation< - ti::CopyConstructibleProfile, ti::CopyConstructibleArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::nothrow, - ti::copy_constructible::yes, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::nothrow>>, - - // NothrowMovable - ProfileAndExpectation< - ti::NothrowMovableProfile, ti::NothrowMovableArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::nothrow, - ti::copy_constructible::maybe, ti::move_assignable::nothrow, - ti::copy_assignable::maybe, ti::destructible::nothrow, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::maybe, ti::swappable::nothrow>>, - - // Value - ProfileAndExpectation< - ti::ValueProfile, ti::ValueArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::nothrow, - ti::copy_constructible::yes, ti::move_assignable::nothrow, - ti::copy_assignable::yes, ti::destructible::nothrow, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::maybe, ti::swappable::nothrow>>, - - //////////////////////////////////////////////////////////////////////////// - // Common but also DefaultConstructible // - //////////////////////////////////////////////////////////////////////////// - - // DefaultConstructibleNothrowMoveConstructible - ProfileAndExpectation< - ti::DefaultConstructibleNothrowMoveConstructibleProfile, - ti::DefaultConstructibleNothrowMoveConstructibleArchetype, - ti::ConformanceProfile< - ti::default_constructible::yes, ti::move_constructible::nothrow, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::nothrow>>, - - // DefaultConstructibleCopyConstructible - ProfileAndExpectation< - ti::DefaultConstructibleCopyConstructibleProfile, - ti::DefaultConstructibleCopyConstructibleArchetype, - ti::ConformanceProfile< - ti::default_constructible::yes, ti::move_constructible::nothrow, - ti::copy_constructible::yes, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::nothrow>>, - - // DefaultConstructibleNothrowMovable - ProfileAndExpectation< - ti::DefaultConstructibleNothrowMovableProfile, - ti::DefaultConstructibleNothrowMovableArchetype, - ti::ConformanceProfile< - ti::default_constructible::yes, ti::move_constructible::nothrow, - ti::copy_constructible::maybe, ti::move_assignable::nothrow, - ti::copy_assignable::maybe, ti::destructible::nothrow, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::maybe, ti::swappable::nothrow>>, - - // DefaultConstructibleValue - ProfileAndExpectation< - ti::DefaultConstructibleValueProfile, - ti::DefaultConstructibleValueArchetype, - ti::ConformanceProfile< - ti::default_constructible::yes, ti::move_constructible::nothrow, - ti::copy_constructible::yes, ti::move_assignable::nothrow, - ti::copy_assignable::yes, ti::destructible::nothrow, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::maybe, ti::swappable::nothrow>>>; - -using ComparableHelpersProfilesToTest = ::testing::Types< - // Equatable - ProfileAndExpectation< - ti::EquatableProfile, ti::EquatableArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::yes, ti::inequality_comparable::yes>>, - - // Comparable - ProfileAndExpectation< - ti::ComparableProfile, ti::ComparableArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::yes, ti::inequality_comparable::yes, - ti::less_than_comparable::yes, ti::less_equal_comparable::yes, - ti::greater_equal_comparable::yes, - ti::greater_than_comparable::yes>>, - - // NothrowEquatable - ProfileAndExpectation< - ti::NothrowEquatableProfile, ti::NothrowEquatableArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::nothrow, - ti::inequality_comparable::nothrow>>, - - // NothrowComparable - ProfileAndExpectation< - ti::NothrowComparableProfile, ti::NothrowComparableArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::nothrow, - ti::inequality_comparable::nothrow, - ti::less_than_comparable::nothrow, - ti::less_equal_comparable::nothrow, - ti::greater_equal_comparable::nothrow, - ti::greater_than_comparable::nothrow>>>; - -using CommonComparableProfilesToTest = ::testing::Types< - // ComparableNothrowMoveConstructible - ProfileAndExpectation< - ti::ComparableNothrowMoveConstructibleProfile, - ti::ComparableNothrowMoveConstructibleArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::nothrow, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::nothrow, - ti::equality_comparable::yes, ti::inequality_comparable::yes, - ti::less_than_comparable::yes, ti::less_equal_comparable::yes, - ti::greater_equal_comparable::yes, - ti::greater_than_comparable::yes>>, - - // ComparableCopyConstructible - ProfileAndExpectation< - ti::ComparableCopyConstructibleProfile, - ti::ComparableCopyConstructibleArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::nothrow, - ti::copy_constructible::yes, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::nothrow, - ti::equality_comparable::yes, ti::inequality_comparable::yes, - ti::less_than_comparable::yes, ti::less_equal_comparable::yes, - ti::greater_equal_comparable::yes, - ti::greater_than_comparable::yes>>, - - // ComparableNothrowMovable - ProfileAndExpectation< - ti::ComparableNothrowMovableProfile, - ti::ComparableNothrowMovableArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::nothrow, - ti::copy_constructible::maybe, ti::move_assignable::nothrow, - ti::copy_assignable::maybe, ti::destructible::nothrow, - ti::equality_comparable::yes, ti::inequality_comparable::yes, - ti::less_than_comparable::yes, ti::less_equal_comparable::yes, - ti::greater_equal_comparable::yes, ti::greater_than_comparable::yes, - ti::swappable::nothrow>>, - - // ComparableValue - ProfileAndExpectation< - ti::ComparableValueProfile, ti::ComparableValueArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::nothrow, - ti::copy_constructible::yes, ti::move_assignable::nothrow, - ti::copy_assignable::yes, ti::destructible::nothrow, - ti::equality_comparable::yes, ti::inequality_comparable::yes, - ti::less_than_comparable::yes, ti::less_equal_comparable::yes, - ti::greater_equal_comparable::yes, ti::greater_than_comparable::yes, - ti::swappable::nothrow>>>; - -using TrivialProfilesToTest = ::testing::Types< - ProfileAndExpectation< - ti::TrivialSpecialMemberFunctionsProfile, - ti::TrivialSpecialMemberFunctionsArchetype, - ti::ConformanceProfile< - ti::default_constructible::trivial, ti::move_constructible::trivial, - ti::copy_constructible::trivial, ti::move_assignable::trivial, - ti::copy_assignable::trivial, ti::destructible::trivial, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::maybe, ti::swappable::nothrow>>, - - ProfileAndExpectation< - ti::TriviallyCompleteProfile, ti::TriviallyCompleteArchetype, - ti::ConformanceProfile< - ti::default_constructible::trivial, ti::move_constructible::trivial, - ti::copy_constructible::trivial, ti::move_assignable::trivial, - ti::copy_assignable::trivial, ti::destructible::trivial, - ti::equality_comparable::yes, ti::inequality_comparable::yes, - ti::less_than_comparable::yes, ti::less_equal_comparable::yes, - ti::greater_equal_comparable::yes, ti::greater_than_comparable::yes, - ti::swappable::nothrow, ti::hashable::yes>>>; - -INSTANTIATE_TYPED_TEST_SUITE_P(Core, ProfileTest, CoreProfilesToTest); -INSTANTIATE_TYPED_TEST_SUITE_P(Common, ProfileTest, CommonProfilesToTest); -INSTANTIATE_TYPED_TEST_SUITE_P(ComparableHelpers, ProfileTest, - ComparableHelpersProfilesToTest); -INSTANTIATE_TYPED_TEST_SUITE_P(CommonComparable, ProfileTest, - CommonComparableProfilesToTest); -INSTANTIATE_TYPED_TEST_SUITE_P(Trivial, ProfileTest, TrivialProfilesToTest); - -TEST(ConformanceTestingTest, Basic) { - using profile = ti::CombineProfiles<ti::TriviallyCompleteProfile, - ti::NothrowComparableProfile>; - - using lim = std::numeric_limits<float>; - - ABSL_INTERNAL_ASSERT_CONFORMANCE_OF(float) - .INITIALIZER(-lim::infinity()) - .INITIALIZER(lim::lowest()) - .INITIALIZER(-1.f) - .INITIALIZER(-lim::min()) - .EQUIVALENCE_CLASS(INITIALIZER(-0.f), INITIALIZER(0.f)) - .INITIALIZER(lim::min()) - .INITIALIZER(1.f) - .INITIALIZER(lim::max()) - .INITIALIZER(lim::infinity()) - .WITH_STRICT_PROFILE(absl::types_internal::RegularityDomain, profile); -} - -struct BadMoveConstruct { - BadMoveConstruct() = default; - BadMoveConstruct(BadMoveConstruct&& other) noexcept - : value(other.value + 1) {} - BadMoveConstruct& operator=(BadMoveConstruct&& other) noexcept = default; - int value = 0; - - friend bool operator==(BadMoveConstruct const& lhs, - BadMoveConstruct const& rhs) { - return lhs.value == rhs.value; - } - friend bool operator!=(BadMoveConstruct const& lhs, - BadMoveConstruct const& rhs) { - return lhs.value != rhs.value; - } -}; - -struct BadMoveAssign { - BadMoveAssign() = default; - BadMoveAssign(BadMoveAssign&& other) noexcept = default; - BadMoveAssign& operator=(BadMoveAssign&& other) noexcept { - int new_value = other.value + 1; - value = new_value; - return *this; - } - int value = 0; - - friend bool operator==(BadMoveAssign const& lhs, BadMoveAssign const& rhs) { - return lhs.value == rhs.value; - } - friend bool operator!=(BadMoveAssign const& lhs, BadMoveAssign const& rhs) { - return lhs.value != rhs.value; - } -}; - -enum class WhichCompIsBad { eq, ne, lt, le, ge, gt }; - -template <WhichCompIsBad Which> -struct BadCompare { - int value; - - friend bool operator==(BadCompare const& lhs, BadCompare const& rhs) { - return Which == WhichCompIsBad::eq ? lhs.value != rhs.value - : lhs.value == rhs.value; - } - - friend bool operator!=(BadCompare const& lhs, BadCompare const& rhs) { - return Which == WhichCompIsBad::ne ? lhs.value == rhs.value - : lhs.value != rhs.value; - } - - friend bool operator<(BadCompare const& lhs, BadCompare const& rhs) { - return Which == WhichCompIsBad::lt ? lhs.value >= rhs.value - : lhs.value < rhs.value; - } - - friend bool operator<=(BadCompare const& lhs, BadCompare const& rhs) { - return Which == WhichCompIsBad::le ? lhs.value > rhs.value - : lhs.value <= rhs.value; - } - - friend bool operator>=(BadCompare const& lhs, BadCompare const& rhs) { - return Which == WhichCompIsBad::ge ? lhs.value < rhs.value - : lhs.value >= rhs.value; - } - - friend bool operator>(BadCompare const& lhs, BadCompare const& rhs) { - return Which == WhichCompIsBad::gt ? lhs.value <= rhs.value - : lhs.value > rhs.value; - } -}; - -TEST(ConformanceTestingDeathTest, Failures) { - { - using profile = ti::CombineProfiles<ti::TriviallyCompleteProfile, - ti::NothrowComparableProfile>; - - // Note: The initializers are intentionally in the wrong order. - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(float) - .INITIALIZER(1.f) - .INITIALIZER(0.f) - .WITH_LOOSE_PROFILE(profile); - } - - { - using profile = - ti::CombineProfiles<ti::NothrowMovableProfile, ti::EquatableProfile>; - - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadMoveConstruct) - .DUE_TO("Move construction") - .INITIALIZER(BadMoveConstruct()) - .WITH_LOOSE_PROFILE(profile); - } - - { - using profile = - ti::CombineProfiles<ti::NothrowMovableProfile, ti::EquatableProfile>; - - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadMoveAssign) - .DUE_TO("Move assignment") - .INITIALIZER(BadMoveAssign()) - .WITH_LOOSE_PROFILE(profile); - } -} - -TEST(ConformanceTestingDeathTest, CompFailures) { - using profile = ti::ComparableProfile; - - { - using BadComp = BadCompare<WhichCompIsBad::eq>; - - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp) - .DUE_TO("Comparison") - .INITIALIZER(BadComp{0}) - .INITIALIZER(BadComp{1}) - .WITH_LOOSE_PROFILE(profile); - } - - { - using BadComp = BadCompare<WhichCompIsBad::ne>; - - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp) - .DUE_TO("Comparison") - .INITIALIZER(BadComp{0}) - .INITIALIZER(BadComp{1}) - .WITH_LOOSE_PROFILE(profile); - } - - { - using BadComp = BadCompare<WhichCompIsBad::lt>; - - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp) - .DUE_TO("Comparison") - .INITIALIZER(BadComp{0}) - .INITIALIZER(BadComp{1}) - .WITH_LOOSE_PROFILE(profile); - } - - { - using BadComp = BadCompare<WhichCompIsBad::le>; - - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp) - .DUE_TO("Comparison") - .INITIALIZER(BadComp{0}) - .INITIALIZER(BadComp{1}) - .WITH_LOOSE_PROFILE(profile); - } - - { - using BadComp = BadCompare<WhichCompIsBad::ge>; - - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp) - .DUE_TO("Comparison") - .INITIALIZER(BadComp{0}) - .INITIALIZER(BadComp{1}) - .WITH_LOOSE_PROFILE(profile); - } - - { - using BadComp = BadCompare<WhichCompIsBad::gt>; - - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp) - .DUE_TO("Comparison") - .INITIALIZER(BadComp{0}) - .INITIALIZER(BadComp{1}) - .WITH_LOOSE_PROFILE(profile); - } -} - -struct BadSelfMove { - BadSelfMove() = default; - BadSelfMove(BadSelfMove&&) = default; - BadSelfMove& operator=(BadSelfMove&& other) noexcept { - if (this == &other) { - broken_state = true; - } - return *this; - } - - friend bool operator==(const BadSelfMove& lhs, const BadSelfMove& rhs) { - return !(lhs.broken_state || rhs.broken_state); - } - - friend bool operator!=(const BadSelfMove& lhs, const BadSelfMove& rhs) { - return lhs.broken_state || rhs.broken_state; - } - - bool broken_state = false; -}; - -TEST(ConformanceTestingDeathTest, SelfMoveFailure) { - using profile = ti::EquatableNothrowMovableProfile; - - { - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadSelfMove) - .DUE_TO("Move assignment") - .INITIALIZER(BadSelfMove()) - .WITH_LOOSE_PROFILE(profile); - } -} - -struct BadSelfCopy { - BadSelfCopy() = default; - BadSelfCopy(BadSelfCopy&&) = default; - BadSelfCopy(const BadSelfCopy&) = default; - BadSelfCopy& operator=(BadSelfCopy&&) = default; - BadSelfCopy& operator=(BadSelfCopy const& other) { - if (this == &other) { - broken_state = true; - } - return *this; - } - - friend bool operator==(const BadSelfCopy& lhs, const BadSelfCopy& rhs) { - return !(lhs.broken_state || rhs.broken_state); - } - - friend bool operator!=(const BadSelfCopy& lhs, const BadSelfCopy& rhs) { - return lhs.broken_state || rhs.broken_state; - } - - bool broken_state = false; -}; - -TEST(ConformanceTestingDeathTest, SelfCopyFailure) { - using profile = ti::EquatableValueProfile; - - { - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadSelfCopy) - .DUE_TO("Copy assignment") - .INITIALIZER(BadSelfCopy()) - .WITH_LOOSE_PROFILE(profile); - } -} - -struct BadSelfSwap { - friend void swap(BadSelfSwap& lhs, BadSelfSwap& rhs) noexcept { - if (&lhs == &rhs) lhs.broken_state = true; - } - - friend bool operator==(const BadSelfSwap& lhs, const BadSelfSwap& rhs) { - return !(lhs.broken_state || rhs.broken_state); - } - - friend bool operator!=(const BadSelfSwap& lhs, const BadSelfSwap& rhs) { - return lhs.broken_state || rhs.broken_state; - } - - bool broken_state = false; -}; - -TEST(ConformanceTestingDeathTest, SelfSwapFailure) { - using profile = ti::EquatableNothrowMovableProfile; - - { - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadSelfSwap) - .DUE_TO("Swap") - .INITIALIZER(BadSelfSwap()) - .WITH_LOOSE_PROFILE(profile); - } -} - -struct BadDefaultInitializedMoveAssign { - BadDefaultInitializedMoveAssign() : default_initialized(true) {} - explicit BadDefaultInitializedMoveAssign(int v) : value(v) {} - BadDefaultInitializedMoveAssign( - BadDefaultInitializedMoveAssign&& other) noexcept - : value(other.value) {} - BadDefaultInitializedMoveAssign& operator=( - BadDefaultInitializedMoveAssign&& other) noexcept { - value = other.value; - if (default_initialized) ++value; // Bad move if lhs is default initialized - return *this; - } - - friend bool operator==(const BadDefaultInitializedMoveAssign& lhs, - const BadDefaultInitializedMoveAssign& rhs) { - return lhs.value == rhs.value; - } - - friend bool operator!=(const BadDefaultInitializedMoveAssign& lhs, - const BadDefaultInitializedMoveAssign& rhs) { - return lhs.value != rhs.value; - } - - bool default_initialized = false; - int value = 0; -}; - -TEST(ConformanceTestingDeathTest, DefaultInitializedMoveAssignFailure) { - using profile = - ti::CombineProfiles<ti::DefaultConstructibleNothrowMovableProfile, - ti::EquatableProfile>; - - { - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadDefaultInitializedMoveAssign) - .DUE_TO("move assignment") - .INITIALIZER(BadDefaultInitializedMoveAssign(0)) - .WITH_LOOSE_PROFILE(profile); - } -} - -struct BadDefaultInitializedCopyAssign { - BadDefaultInitializedCopyAssign() : default_initialized(true) {} - explicit BadDefaultInitializedCopyAssign(int v) : value(v) {} - BadDefaultInitializedCopyAssign( - BadDefaultInitializedCopyAssign&& other) noexcept - : value(other.value) {} - BadDefaultInitializedCopyAssign(const BadDefaultInitializedCopyAssign& other) - : value(other.value) {} - - BadDefaultInitializedCopyAssign& operator=( - BadDefaultInitializedCopyAssign&& other) noexcept { - value = other.value; - return *this; - } - - BadDefaultInitializedCopyAssign& operator=( - const BadDefaultInitializedCopyAssign& other) { - value = other.value; - if (default_initialized) ++value; // Bad move if lhs is default initialized - return *this; - } - - friend bool operator==(const BadDefaultInitializedCopyAssign& lhs, - const BadDefaultInitializedCopyAssign& rhs) { - return lhs.value == rhs.value; - } - - friend bool operator!=(const BadDefaultInitializedCopyAssign& lhs, - const BadDefaultInitializedCopyAssign& rhs) { - return lhs.value != rhs.value; - } - - bool default_initialized = false; - int value = 0; -}; - -TEST(ConformanceTestingDeathTest, DefaultInitializedAssignFailure) { - using profile = ti::CombineProfiles<ti::DefaultConstructibleValueProfile, - ti::EquatableProfile>; - - { - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadDefaultInitializedCopyAssign) - .DUE_TO("copy assignment") - .INITIALIZER(BadDefaultInitializedCopyAssign(0)) - .WITH_LOOSE_PROFILE(profile); - } -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/types/internal/optional.h b/third_party/abseil_cpp/absl/types/internal/optional.h deleted file mode 100644 index 92932b6001b3..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/optional.h +++ /dev/null @@ -1,396 +0,0 @@ -// Copyright 2017 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#ifndef ABSL_TYPES_INTERNAL_OPTIONAL_H_ -#define ABSL_TYPES_INTERNAL_OPTIONAL_H_ - -#include <functional> -#include <new> -#include <type_traits> -#include <utility> - -#include "absl/base/internal/inline_variable.h" -#include "absl/memory/memory.h" -#include "absl/meta/type_traits.h" -#include "absl/utility/utility.h" - -// ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS -// -// Inheriting constructors is supported in GCC 4.8+, Clang 3.3+ and MSVC 2015. -// __cpp_inheriting_constructors is a predefined macro and a recommended way to -// check for this language feature, but GCC doesn't support it until 5.0 and -// Clang doesn't support it until 3.6. -// Also, MSVC 2015 has a bug: it doesn't inherit the constexpr template -// constructor. For example, the following code won't work on MSVC 2015 Update3: -// struct Base { -// int t; -// template <typename T> -// constexpr Base(T t_) : t(t_) {} -// }; -// struct Foo : Base { -// using Base::Base; -// } -// constexpr Foo foo(0); // doesn't work on MSVC 2015 -#if defined(__clang__) -#if __has_feature(cxx_inheriting_constructors) -#define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1 -#endif -#elif (defined(__GNUC__) && \ - (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 8)) || \ - (__cpp_inheriting_constructors >= 200802) || \ - (defined(_MSC_VER) && _MSC_VER >= 1910) -#define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1 -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// Forward declaration -template <typename T> -class optional; - -namespace optional_internal { - -// This tag type is used as a constructor parameter type for `nullopt_t`. -struct init_t { - explicit init_t() = default; -}; - -struct empty_struct {}; - -// This class stores the data in optional<T>. -// It is specialized based on whether T is trivially destructible. -// This is the specialization for non trivially destructible type. -template <typename T, bool unused = std::is_trivially_destructible<T>::value> -class optional_data_dtor_base { - struct dummy_type { - static_assert(sizeof(T) % sizeof(empty_struct) == 0, ""); - // Use an array to avoid GCC 6 placement-new warning. - empty_struct data[sizeof(T) / sizeof(empty_struct)]; - }; - - protected: - // Whether there is data or not. - bool engaged_; - // Data storage - union { - T data_; - dummy_type dummy_; - }; - - void destruct() noexcept { - if (engaged_) { - data_.~T(); - engaged_ = false; - } - } - - // dummy_ must be initialized for constexpr constructor. - constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {} - - template <typename... Args> - constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args) - : engaged_(true), data_(absl::forward<Args>(args)...) {} - - ~optional_data_dtor_base() { destruct(); } -}; - -// Specialization for trivially destructible type. -template <typename T> -class optional_data_dtor_base<T, true> { - struct dummy_type { - static_assert(sizeof(T) % sizeof(empty_struct) == 0, ""); - // Use array to avoid GCC 6 placement-new warning. - empty_struct data[sizeof(T) / sizeof(empty_struct)]; - }; - - protected: - // Whether there is data or not. - bool engaged_; - // Data storage - union { - T data_; - dummy_type dummy_; - }; - void destruct() noexcept { engaged_ = false; } - - // dummy_ must be initialized for constexpr constructor. - constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {} - - template <typename... Args> - constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args) - : engaged_(true), data_(absl::forward<Args>(args)...) {} -}; - -template <typename T> -class optional_data_base : public optional_data_dtor_base<T> { - protected: - using base = optional_data_dtor_base<T>; -#ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS - using base::base; -#else - optional_data_base() = default; - - template <typename... Args> - constexpr explicit optional_data_base(in_place_t t, Args&&... args) - : base(t, absl::forward<Args>(args)...) {} -#endif - - template <typename... Args> - void construct(Args&&... args) { - // Use dummy_'s address to work around casting cv-qualified T* to void*. - ::new (static_cast<void*>(&this->dummy_)) T(std::forward<Args>(args)...); - this->engaged_ = true; - } - - template <typename U> - void assign(U&& u) { - if (this->engaged_) { - this->data_ = std::forward<U>(u); - } else { - construct(std::forward<U>(u)); - } - } -}; - -// TODO(absl-team): Add another class using -// std::is_trivially_move_constructible trait when available to match -// http://cplusplus.github.io/LWG/lwg-defects.html#2900, for types that -// have trivial move but nontrivial copy. -// Also, we should be checking is_trivially_copyable here, which is not -// supported now, so we use is_trivially_* traits instead. -template <typename T, - bool unused = absl::is_trivially_copy_constructible<T>::value&& - absl::is_trivially_copy_assignable<typename std::remove_cv< - T>::type>::value&& std::is_trivially_destructible<T>::value> -class optional_data; - -// Trivially copyable types -template <typename T> -class optional_data<T, true> : public optional_data_base<T> { - protected: -#ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS - using optional_data_base<T>::optional_data_base; -#else - optional_data() = default; - - template <typename... Args> - constexpr explicit optional_data(in_place_t t, Args&&... args) - : optional_data_base<T>(t, absl::forward<Args>(args)...) {} -#endif -}; - -template <typename T> -class optional_data<T, false> : public optional_data_base<T> { - protected: -#ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS - using optional_data_base<T>::optional_data_base; -#else - template <typename... Args> - constexpr explicit optional_data(in_place_t t, Args&&... args) - : optional_data_base<T>(t, absl::forward<Args>(args)...) {} -#endif - - optional_data() = default; - - optional_data(const optional_data& rhs) : optional_data_base<T>() { - if (rhs.engaged_) { - this->construct(rhs.data_); - } - } - - optional_data(optional_data&& rhs) noexcept( - absl::default_allocator_is_nothrow::value || - std::is_nothrow_move_constructible<T>::value) - : optional_data_base<T>() { - if (rhs.engaged_) { - this->construct(std::move(rhs.data_)); - } - } - - optional_data& operator=(const optional_data& rhs) { - if (rhs.engaged_) { - this->assign(rhs.data_); - } else { - this->destruct(); - } - return *this; - } - - optional_data& operator=(optional_data&& rhs) noexcept( - std::is_nothrow_move_assignable<T>::value&& - std::is_nothrow_move_constructible<T>::value) { - if (rhs.engaged_) { - this->assign(std::move(rhs.data_)); - } else { - this->destruct(); - } - return *this; - } -}; - -// Ordered by level of restriction, from low to high. -// Copyable implies movable. -enum class copy_traits { copyable = 0, movable = 1, non_movable = 2 }; - -// Base class for enabling/disabling copy/move constructor. -template <copy_traits> -class optional_ctor_base; - -template <> -class optional_ctor_base<copy_traits::copyable> { - public: - constexpr optional_ctor_base() = default; - optional_ctor_base(const optional_ctor_base&) = default; - optional_ctor_base(optional_ctor_base&&) = default; - optional_ctor_base& operator=(const optional_ctor_base&) = default; - optional_ctor_base& operator=(optional_ctor_base&&) = default; -}; - -template <> -class optional_ctor_base<copy_traits::movable> { - public: - constexpr optional_ctor_base() = default; - optional_ctor_base(const optional_ctor_base&) = delete; - optional_ctor_base(optional_ctor_base&&) = default; - optional_ctor_base& operator=(const optional_ctor_base&) = default; - optional_ctor_base& operator=(optional_ctor_base&&) = default; -}; - -template <> -class optional_ctor_base<copy_traits::non_movable> { - public: - constexpr optional_ctor_base() = default; - optional_ctor_base(const optional_ctor_base&) = delete; - optional_ctor_base(optional_ctor_base&&) = delete; - optional_ctor_base& operator=(const optional_ctor_base&) = default; - optional_ctor_base& operator=(optional_ctor_base&&) = default; -}; - -// Base class for enabling/disabling copy/move assignment. -template <copy_traits> -class optional_assign_base; - -template <> -class optional_assign_base<copy_traits::copyable> { - public: - constexpr optional_assign_base() = default; - optional_assign_base(const optional_assign_base&) = default; - optional_assign_base(optional_assign_base&&) = default; - optional_assign_base& operator=(const optional_assign_base&) = default; - optional_assign_base& operator=(optional_assign_base&&) = default; -}; - -template <> -class optional_assign_base<copy_traits::movable> { - public: - constexpr optional_assign_base() = default; - optional_assign_base(const optional_assign_base&) = default; - optional_assign_base(optional_assign_base&&) = default; - optional_assign_base& operator=(const optional_assign_base&) = delete; - optional_assign_base& operator=(optional_assign_base&&) = default; -}; - -template <> -class optional_assign_base<copy_traits::non_movable> { - public: - constexpr optional_assign_base() = default; - optional_assign_base(const optional_assign_base&) = default; - optional_assign_base(optional_assign_base&&) = default; - optional_assign_base& operator=(const optional_assign_base&) = delete; - optional_assign_base& operator=(optional_assign_base&&) = delete; -}; - -template <typename T> -struct ctor_copy_traits { - static constexpr copy_traits traits = - std::is_copy_constructible<T>::value - ? copy_traits::copyable - : std::is_move_constructible<T>::value ? copy_traits::movable - : copy_traits::non_movable; -}; - -template <typename T> -struct assign_copy_traits { - static constexpr copy_traits traits = - absl::is_copy_assignable<T>::value && std::is_copy_constructible<T>::value - ? copy_traits::copyable - : absl::is_move_assignable<T>::value && - std::is_move_constructible<T>::value - ? copy_traits::movable - : copy_traits::non_movable; -}; - -// Whether T is constructible or convertible from optional<U>. -template <typename T, typename U> -struct is_constructible_convertible_from_optional - : std::integral_constant< - bool, std::is_constructible<T, optional<U>&>::value || - std::is_constructible<T, optional<U>&&>::value || - std::is_constructible<T, const optional<U>&>::value || - std::is_constructible<T, const optional<U>&&>::value || - std::is_convertible<optional<U>&, T>::value || - std::is_convertible<optional<U>&&, T>::value || - std::is_convertible<const optional<U>&, T>::value || - std::is_convertible<const optional<U>&&, T>::value> {}; - -// Whether T is constructible or convertible or assignable from optional<U>. -template <typename T, typename U> -struct is_constructible_convertible_assignable_from_optional - : std::integral_constant< - bool, is_constructible_convertible_from_optional<T, U>::value || - std::is_assignable<T&, optional<U>&>::value || - std::is_assignable<T&, optional<U>&&>::value || - std::is_assignable<T&, const optional<U>&>::value || - std::is_assignable<T&, const optional<U>&&>::value> {}; - -// Helper function used by [optional.relops], [optional.comp_with_t], -// for checking whether an expression is convertible to bool. -bool convertible_to_bool(bool); - -// Base class for std::hash<absl::optional<T>>: -// If std::hash<std::remove_const_t<T>> is enabled, it provides operator() to -// compute the hash; Otherwise, it is disabled. -// Reference N4659 23.14.15 [unord.hash]. -template <typename T, typename = size_t> -struct optional_hash_base { - optional_hash_base() = delete; - optional_hash_base(const optional_hash_base&) = delete; - optional_hash_base(optional_hash_base&&) = delete; - optional_hash_base& operator=(const optional_hash_base&) = delete; - optional_hash_base& operator=(optional_hash_base&&) = delete; -}; - -template <typename T> -struct optional_hash_base<T, decltype(std::hash<absl::remove_const_t<T> >()( - std::declval<absl::remove_const_t<T> >()))> { - using argument_type = absl::optional<T>; - using result_type = size_t; - size_t operator()(const absl::optional<T>& opt) const { - absl::type_traits_internal::AssertHashEnabled<absl::remove_const_t<T>>(); - if (opt) { - return std::hash<absl::remove_const_t<T> >()(*opt); - } else { - return static_cast<size_t>(0x297814aaad196e6dULL); - } - } -}; - -} // namespace optional_internal -ABSL_NAMESPACE_END -} // namespace absl - -#undef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS - -#endif // ABSL_TYPES_INTERNAL_OPTIONAL_H_ diff --git a/third_party/abseil_cpp/absl/types/internal/parentheses.h b/third_party/abseil_cpp/absl/types/internal/parentheses.h deleted file mode 100644 index 5aebee8fdeb9..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/parentheses.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2019 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------- -// parentheses.h -// ----------------------------------------------------------------------------- -// -// This file contains macros that expand to a left parenthesis and a right -// parenthesis. These are in their own file and are generated from macros -// because otherwise clang-format gets confused and clang-format off directives -// do not help. -// -// The parentheses macros are used when wanting to require a rescan before -// expansion of parenthesized text appearing after a function-style macro name. - -#ifndef ABSL_TYPES_INTERNAL_PARENTHESES_H_ -#define ABSL_TYPES_INTERNAL_PARENTHESES_H_ - -#define ABSL_INTERNAL_LPAREN ( - -#define ABSL_INTERNAL_RPAREN ) - -#endif // ABSL_TYPES_INTERNAL_PARENTHESES_H_ diff --git a/third_party/abseil_cpp/absl/types/internal/span.h b/third_party/abseil_cpp/absl/types/internal/span.h deleted file mode 100644 index 112612f4bdae..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/span.h +++ /dev/null @@ -1,128 +0,0 @@ -// -// Copyright 2019 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#ifndef ABSL_TYPES_INTERNAL_SPAN_H_ -#define ABSL_TYPES_INTERNAL_SPAN_H_ - -#include <algorithm> -#include <cstddef> -#include <string> -#include <type_traits> - -#include "absl/algorithm/algorithm.h" -#include "absl/base/internal/throw_delegate.h" -#include "absl/meta/type_traits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -namespace span_internal { -// A constexpr min function -constexpr size_t Min(size_t a, size_t b) noexcept { return a < b ? a : b; } - -// Wrappers for access to container data pointers. -template <typename C> -constexpr auto GetDataImpl(C& c, char) noexcept // NOLINT(runtime/references) - -> decltype(c.data()) { - return c.data(); -} - -// Before C++17, std::string::data returns a const char* in all cases. -inline char* GetDataImpl(std::string& s, // NOLINT(runtime/references) - int) noexcept { - return &s[0]; -} - -template <typename C> -constexpr auto GetData(C& c) noexcept // NOLINT(runtime/references) - -> decltype(GetDataImpl(c, 0)) { - return GetDataImpl(c, 0); -} - -// Detection idioms for size() and data(). -template <typename C> -using HasSize = - std::is_integral<absl::decay_t<decltype(std::declval<C&>().size())>>; - -// We want to enable conversion from vector<T*> to Span<const T* const> but -// disable conversion from vector<Derived> to Span<Base>. Here we use -// the fact that U** is convertible to Q* const* if and only if Q is the same -// type or a more cv-qualified version of U. We also decay the result type of -// data() to avoid problems with classes which have a member function data() -// which returns a reference. -template <typename T, typename C> -using HasData = - std::is_convertible<absl::decay_t<decltype(GetData(std::declval<C&>()))>*, - T* const*>; - -// Extracts value type from a Container -template <typename C> -struct ElementType { - using type = typename absl::remove_reference_t<C>::value_type; -}; - -template <typename T, size_t N> -struct ElementType<T (&)[N]> { - using type = T; -}; - -template <typename C> -using ElementT = typename ElementType<C>::type; - -template <typename T> -using EnableIfMutable = - typename std::enable_if<!std::is_const<T>::value, int>::type; - -template <template <typename> class SpanT, typename T> -bool EqualImpl(SpanT<T> a, SpanT<T> b) { - static_assert(std::is_const<T>::value, ""); - return absl::equal(a.begin(), a.end(), b.begin(), b.end()); -} - -template <template <typename> class SpanT, typename T> -bool LessThanImpl(SpanT<T> a, SpanT<T> b) { - // We can't use value_type since that is remove_cv_t<T>, so we go the long way - // around. - static_assert(std::is_const<T>::value, ""); - return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()); -} - -// The `IsConvertible` classes here are needed because of the -// `std::is_convertible` bug in libcxx when compiled with GCC. This build -// configuration is used by Android NDK toolchain. Reference link: -// https://bugs.llvm.org/show_bug.cgi?id=27538. -template <typename From, typename To> -struct IsConvertibleHelper { - private: - static std::true_type testval(To); - static std::false_type testval(...); - - public: - using type = decltype(testval(std::declval<From>())); -}; - -template <typename From, typename To> -struct IsConvertible : IsConvertibleHelper<From, To>::type {}; - -// TODO(zhangxy): replace `IsConvertible` with `std::is_convertible` once the -// older version of libcxx is not supported. -template <typename From, typename To> -using EnableIfConvertibleTo = - typename std::enable_if<IsConvertible<From, To>::value>::type; -} // namespace span_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TYPES_INTERNAL_SPAN_H_ diff --git a/third_party/abseil_cpp/absl/types/internal/transform_args.h b/third_party/abseil_cpp/absl/types/internal/transform_args.h deleted file mode 100644 index 4a0ab42ac49f..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/transform_args.h +++ /dev/null @@ -1,246 +0,0 @@ -// Copyright 2019 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------- -// transform_args.h -// ----------------------------------------------------------------------------- -// -// This file contains a higher-order macro that "transforms" each element of a -// a variadic argument by a provided secondary macro. - -#ifndef ABSL_TYPES_INTERNAL_TRANSFORM_ARGS_H_ -#define ABSL_TYPES_INTERNAL_TRANSFORM_ARGS_H_ - -// -// ABSL_INTERNAL_CAT(a, b) -// -// This macro takes two arguments and concatenates them together via ## after -// expansion. -// -// Example: -// -// ABSL_INTERNAL_CAT(foo_, bar) -// -// Results in: -// -// foo_bar -#define ABSL_INTERNAL_CAT(a, b) ABSL_INTERNAL_CAT_IMPL(a, b) -#define ABSL_INTERNAL_CAT_IMPL(a, b) a##b - -// -// ABSL_INTERNAL_TRANSFORM_ARGS(m, ...) -// -// This macro takes another macro as an argument followed by a trailing series -// of additional parameters (up to 32 additional arguments). It invokes the -// passed-in macro once for each of the additional arguments, with the -// expansions separated by commas. -// -// Example: -// -// ABSL_INTERNAL_TRANSFORM_ARGS(MY_MACRO, a, b, c) -// -// Results in: -// -// MY_MACRO(a), MY_MACRO(b), MY_MACRO(c) -// -// TODO(calabrese) Handle no arguments as a special case. -#define ABSL_INTERNAL_TRANSFORM_ARGS(m, ...) \ - ABSL_INTERNAL_CAT(ABSL_INTERNAL_TRANSFORM_ARGS, \ - ABSL_INTERNAL_NUM_ARGS(__VA_ARGS__)) \ - (m, __VA_ARGS__) - -#define ABSL_INTERNAL_TRANSFORM_ARGS1(m, a0) m(a0) - -#define ABSL_INTERNAL_TRANSFORM_ARGS2(m, a0, a1) m(a0), m(a1) - -#define ABSL_INTERNAL_TRANSFORM_ARGS3(m, a0, a1, a2) m(a0), m(a1), m(a2) - -#define ABSL_INTERNAL_TRANSFORM_ARGS4(m, a0, a1, a2, a3) \ - m(a0), m(a1), m(a2), m(a3) - -#define ABSL_INTERNAL_TRANSFORM_ARGS5(m, a0, a1, a2, a3, a4) \ - m(a0), m(a1), m(a2), m(a3), m(a4) - -#define ABSL_INTERNAL_TRANSFORM_ARGS6(m, a0, a1, a2, a3, a4, a5) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5) - -#define ABSL_INTERNAL_TRANSFORM_ARGS7(m, a0, a1, a2, a3, a4, a5, a6) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6) - -#define ABSL_INTERNAL_TRANSFORM_ARGS8(m, a0, a1, a2, a3, a4, a5, a6, a7) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7) - -#define ABSL_INTERNAL_TRANSFORM_ARGS9(m, a0, a1, a2, a3, a4, a5, a6, a7, a8) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8) - -#define ABSL_INTERNAL_TRANSFORM_ARGS10(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9) - -#define ABSL_INTERNAL_TRANSFORM_ARGS11(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), m(a10) - -#define ABSL_INTERNAL_TRANSFORM_ARGS12(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11) - -#define ABSL_INTERNAL_TRANSFORM_ARGS13(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12) - -#define ABSL_INTERNAL_TRANSFORM_ARGS14(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13) - -#define ABSL_INTERNAL_TRANSFORM_ARGS15(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14) - -#define ABSL_INTERNAL_TRANSFORM_ARGS16(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14, a15) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15) - -#define ABSL_INTERNAL_TRANSFORM_ARGS17(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14, a15, a16) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16) - -#define ABSL_INTERNAL_TRANSFORM_ARGS18(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14, a15, a16, \ - a17) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17) - -#define ABSL_INTERNAL_TRANSFORM_ARGS19(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14, a15, a16, \ - a17, a18) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18) - -#define ABSL_INTERNAL_TRANSFORM_ARGS20(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14, a15, a16, \ - a17, a18, a19) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19) - -#define ABSL_INTERNAL_TRANSFORM_ARGS21(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14, a15, a16, \ - a17, a18, a19, a20) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19), m(a20) - -#define ABSL_INTERNAL_TRANSFORM_ARGS22(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14, a15, a16, \ - a17, a18, a19, a20, a21) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19), m(a20), m(a21) - -#define ABSL_INTERNAL_TRANSFORM_ARGS23(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14, a15, a16, \ - a17, a18, a19, a20, a21, a22) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19), m(a20), m(a21), m(a22) - -#define ABSL_INTERNAL_TRANSFORM_ARGS24(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14, a15, a16, \ - a17, a18, a19, a20, a21, a22, a23) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19), m(a20), m(a21), m(a22), m(a23) - -#define ABSL_INTERNAL_TRANSFORM_ARGS25(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14, a15, a16, \ - a17, a18, a19, a20, a21, a22, a23, a24) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19), m(a20), m(a21), m(a22), m(a23), m(a24) - -#define ABSL_INTERNAL_TRANSFORM_ARGS26( \ - m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, \ - a16, a17, a18, a19, a20, a21, a22, a23, a24, a25) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25) - -#define ABSL_INTERNAL_TRANSFORM_ARGS27( \ - m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, \ - a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26) - -#define ABSL_INTERNAL_TRANSFORM_ARGS28( \ - m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, \ - a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27) - -#define ABSL_INTERNAL_TRANSFORM_ARGS29( \ - m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, \ - a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27), \ - m(a28) - -#define ABSL_INTERNAL_TRANSFORM_ARGS30( \ - m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, \ - a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27), \ - m(a28), m(a29) - -#define ABSL_INTERNAL_TRANSFORM_ARGS31( \ - m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, \ - a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27), \ - m(a28), m(a29), m(a30) - -#define ABSL_INTERNAL_TRANSFORM_ARGS32(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14, a15, a16, \ - a17, a18, a19, a20, a21, a22, a23, a24, \ - a25, a26, a27, a28, a29, a30, a31) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27), \ - m(a28), m(a29), m(a30), m(a31) - -#define ABSL_INTERNAL_NUM_ARGS_IMPL(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, \ - a10, a11, a12, a13, a14, a15, a16, a17, \ - a18, a19, a20, a21, a22, a23, a24, a25, \ - a26, a27, a28, a29, a30, a31, result, ...) \ - result - -#define ABSL_INTERNAL_FORCE_EXPANSION(...) __VA_ARGS__ - -#define ABSL_INTERNAL_NUM_ARGS(...) \ - ABSL_INTERNAL_FORCE_EXPANSION(ABSL_INTERNAL_NUM_ARGS_IMPL( \ - __VA_ARGS__, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, \ - 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, )) - -#endif // ABSL_TYPES_INTERNAL_TRANSFORM_ARGS_H_ diff --git a/third_party/abseil_cpp/absl/types/internal/variant.h b/third_party/abseil_cpp/absl/types/internal/variant.h deleted file mode 100644 index 772008c74e6d..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/variant.h +++ /dev/null @@ -1,1646 +0,0 @@ -// Copyright 2018 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Implementation details of absl/types/variant.h, pulled into a -// separate file to avoid cluttering the top of the API header with -// implementation details. - -#ifndef ABSL_TYPES_variant_internal_H_ -#define ABSL_TYPES_variant_internal_H_ - -#include <cassert> -#include <cstddef> -#include <cstdlib> -#include <memory> -#include <stdexcept> -#include <tuple> -#include <type_traits> - -#include "absl/base/config.h" -#include "absl/base/internal/identity.h" -#include "absl/base/internal/inline_variable.h" -#include "absl/base/internal/invoke.h" -#include "absl/base/macros.h" -#include "absl/base/optimization.h" -#include "absl/meta/type_traits.h" -#include "absl/types/bad_variant_access.h" -#include "absl/utility/utility.h" - -#if !defined(ABSL_USES_STD_VARIANT) - -namespace absl { -ABSL_NAMESPACE_BEGIN - -template <class... Types> -class variant; - -ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, static_cast<size_t>(-1)); - -template <class T> -struct variant_size; - -template <std::size_t I, class T> -struct variant_alternative; - -namespace variant_internal { - -// NOTE: See specializations below for details. -template <std::size_t I, class T> -struct VariantAlternativeSfinae {}; - -// Requires: I < variant_size_v<T>. -// -// Value: The Ith type of Types... -template <std::size_t I, class T0, class... Tn> -struct VariantAlternativeSfinae<I, variant<T0, Tn...>> - : VariantAlternativeSfinae<I - 1, variant<Tn...>> {}; - -// Value: T0 -template <class T0, class... Ts> -struct VariantAlternativeSfinae<0, variant<T0, Ts...>> { - using type = T0; -}; - -template <std::size_t I, class T> -using VariantAlternativeSfinaeT = typename VariantAlternativeSfinae<I, T>::type; - -// NOTE: Requires T to be a reference type. -template <class T, class U> -struct GiveQualsTo; - -template <class T, class U> -struct GiveQualsTo<T&, U> { - using type = U&; -}; - -template <class T, class U> -struct GiveQualsTo<T&&, U> { - using type = U&&; -}; - -template <class T, class U> -struct GiveQualsTo<const T&, U> { - using type = const U&; -}; - -template <class T, class U> -struct GiveQualsTo<const T&&, U> { - using type = const U&&; -}; - -template <class T, class U> -struct GiveQualsTo<volatile T&, U> { - using type = volatile U&; -}; - -template <class T, class U> -struct GiveQualsTo<volatile T&&, U> { - using type = volatile U&&; -}; - -template <class T, class U> -struct GiveQualsTo<volatile const T&, U> { - using type = volatile const U&; -}; - -template <class T, class U> -struct GiveQualsTo<volatile const T&&, U> { - using type = volatile const U&&; -}; - -template <class T, class U> -using GiveQualsToT = typename GiveQualsTo<T, U>::type; - -// Convenience alias, since size_t integral_constant is used a lot in this file. -template <std::size_t I> -using SizeT = std::integral_constant<std::size_t, I>; - -using NPos = SizeT<variant_npos>; - -template <class Variant, class T, class = void> -struct IndexOfConstructedType {}; - -template <std::size_t I, class Variant> -struct VariantAccessResultImpl; - -template <std::size_t I, template <class...> class Variantemplate, class... T> -struct VariantAccessResultImpl<I, Variantemplate<T...>&> { - using type = typename absl::variant_alternative<I, variant<T...>>::type&; -}; - -template <std::size_t I, template <class...> class Variantemplate, class... T> -struct VariantAccessResultImpl<I, const Variantemplate<T...>&> { - using type = - const typename absl::variant_alternative<I, variant<T...>>::type&; -}; - -template <std::size_t I, template <class...> class Variantemplate, class... T> -struct VariantAccessResultImpl<I, Variantemplate<T...>&&> { - using type = typename absl::variant_alternative<I, variant<T...>>::type&&; -}; - -template <std::size_t I, template <class...> class Variantemplate, class... T> -struct VariantAccessResultImpl<I, const Variantemplate<T...>&&> { - using type = - const typename absl::variant_alternative<I, variant<T...>>::type&&; -}; - -template <std::size_t I, class Variant> -using VariantAccessResult = - typename VariantAccessResultImpl<I, Variant&&>::type; - -// NOTE: This is used instead of std::array to reduce instantiation overhead. -template <class T, std::size_t Size> -struct SimpleArray { - static_assert(Size != 0, ""); - T value[Size]; -}; - -template <class T> -struct AccessedType { - using type = T; -}; - -template <class T> -using AccessedTypeT = typename AccessedType<T>::type; - -template <class T, std::size_t Size> -struct AccessedType<SimpleArray<T, Size>> { - using type = AccessedTypeT<T>; -}; - -template <class T> -constexpr T AccessSimpleArray(const T& value) { - return value; -} - -template <class T, std::size_t Size, class... SizeT> -constexpr AccessedTypeT<T> AccessSimpleArray(const SimpleArray<T, Size>& table, - std::size_t head_index, - SizeT... tail_indices) { - return AccessSimpleArray(table.value[head_index], tail_indices...); -} - -// Note: Intentionally is an alias. -template <class T> -using AlwaysZero = SizeT<0>; - -template <class Op, class... Vs> -struct VisitIndicesResultImpl { - using type = absl::result_of_t<Op(AlwaysZero<Vs>...)>; -}; - -template <class Op, class... Vs> -using VisitIndicesResultT = typename VisitIndicesResultImpl<Op, Vs...>::type; - -template <class ReturnType, class FunctionObject, class EndIndices, - class BoundIndices> -struct MakeVisitationMatrix; - -template <class ReturnType, class FunctionObject, std::size_t... Indices> -constexpr ReturnType call_with_indices(FunctionObject&& function) { - static_assert( - std::is_same<ReturnType, decltype(std::declval<FunctionObject>()( - SizeT<Indices>()...))>::value, - "Not all visitation overloads have the same return type."); - return absl::forward<FunctionObject>(function)(SizeT<Indices>()...); -} - -template <class ReturnType, class FunctionObject, std::size_t... BoundIndices> -struct MakeVisitationMatrix<ReturnType, FunctionObject, index_sequence<>, - index_sequence<BoundIndices...>> { - using ResultType = ReturnType (*)(FunctionObject&&); - static constexpr ResultType Run() { - return &call_with_indices<ReturnType, FunctionObject, - (BoundIndices - 1)...>; - } -}; - -template <typename Is, std::size_t J> -struct AppendToIndexSequence; - -template <typename Is, std::size_t J> -using AppendToIndexSequenceT = typename AppendToIndexSequence<Is, J>::type; - -template <std::size_t... Is, std::size_t J> -struct AppendToIndexSequence<index_sequence<Is...>, J> { - using type = index_sequence<Is..., J>; -}; - -template <class ReturnType, class FunctionObject, class EndIndices, - class CurrIndices, class BoundIndices> -struct MakeVisitationMatrixImpl; - -template <class ReturnType, class FunctionObject, class EndIndices, - std::size_t... CurrIndices, class BoundIndices> -struct MakeVisitationMatrixImpl<ReturnType, FunctionObject, EndIndices, - index_sequence<CurrIndices...>, BoundIndices> { - using ResultType = SimpleArray< - typename MakeVisitationMatrix<ReturnType, FunctionObject, EndIndices, - index_sequence<>>::ResultType, - sizeof...(CurrIndices)>; - - static constexpr ResultType Run() { - return {{MakeVisitationMatrix< - ReturnType, FunctionObject, EndIndices, - AppendToIndexSequenceT<BoundIndices, CurrIndices>>::Run()...}}; - } -}; - -template <class ReturnType, class FunctionObject, std::size_t HeadEndIndex, - std::size_t... TailEndIndices, std::size_t... BoundIndices> -struct MakeVisitationMatrix<ReturnType, FunctionObject, - index_sequence<HeadEndIndex, TailEndIndices...>, - index_sequence<BoundIndices...>> - : MakeVisitationMatrixImpl<ReturnType, FunctionObject, - index_sequence<TailEndIndices...>, - absl::make_index_sequence<HeadEndIndex>, - index_sequence<BoundIndices...>> {}; - -struct UnreachableSwitchCase { - template <class Op> - [[noreturn]] static VisitIndicesResultT<Op, std::size_t> Run( - Op&& /*ignored*/) { -#if ABSL_HAVE_BUILTIN(__builtin_unreachable) || \ - (defined(__GNUC__) && !defined(__clang__)) - __builtin_unreachable(); -#elif defined(_MSC_VER) - __assume(false); -#else - // Try to use assert of false being identified as an unreachable intrinsic. - // NOTE: We use assert directly to increase chances of exploiting an assume - // intrinsic. - assert(false); // NOLINT - - // Hack to silence potential no return warning -- cause an infinite loop. - return Run(absl::forward<Op>(op)); -#endif // Checks for __builtin_unreachable - } -}; - -template <class Op, std::size_t I> -struct ReachableSwitchCase { - static VisitIndicesResultT<Op, std::size_t> Run(Op&& op) { - return absl::base_internal::invoke(absl::forward<Op>(op), SizeT<I>()); - } -}; - -// The number 33 is just a guess at a reasonable maximum to our switch. It is -// not based on any analysis. The reason it is a power of 2 plus 1 instead of a -// power of 2 is because the number was picked to correspond to a power of 2 -// amount of "normal" alternatives, plus one for the possibility of the user -// providing "monostate" in addition to the more natural alternatives. -ABSL_INTERNAL_INLINE_CONSTEXPR(std::size_t, MaxUnrolledVisitCases, 33); - -// Note: The default-definition is for unreachable cases. -template <bool IsReachable> -struct PickCaseImpl { - template <class Op, std::size_t I> - using Apply = UnreachableSwitchCase; -}; - -template <> -struct PickCaseImpl</*IsReachable =*/true> { - template <class Op, std::size_t I> - using Apply = ReachableSwitchCase<Op, I>; -}; - -// Note: This form of dance with template aliases is to make sure that we -// instantiate a number of templates proportional to the number of variant -// alternatives rather than a number of templates proportional to our -// maximum unrolled amount of visitation cases (aliases are effectively -// "free" whereas other template instantiations are costly). -template <class Op, std::size_t I, std::size_t EndIndex> -using PickCase = typename PickCaseImpl<(I < EndIndex)>::template Apply<Op, I>; - -template <class ReturnType> -[[noreturn]] ReturnType TypedThrowBadVariantAccess() { - absl::variant_internal::ThrowBadVariantAccess(); -} - -// Given N variant sizes, determine the number of cases there would need to be -// in a single switch-statement that would cover every possibility in the -// corresponding N-ary visit operation. -template <std::size_t... NumAlternatives> -struct NumCasesOfSwitch; - -template <std::size_t HeadNumAlternatives, std::size_t... TailNumAlternatives> -struct NumCasesOfSwitch<HeadNumAlternatives, TailNumAlternatives...> { - static constexpr std::size_t value = - (HeadNumAlternatives + 1) * - NumCasesOfSwitch<TailNumAlternatives...>::value; -}; - -template <> -struct NumCasesOfSwitch<> { - static constexpr std::size_t value = 1; -}; - -// A switch statement optimizes better than the table of function pointers. -template <std::size_t EndIndex> -struct VisitIndicesSwitch { - static_assert(EndIndex <= MaxUnrolledVisitCases, - "Maximum unrolled switch size exceeded."); - - template <class Op> - static VisitIndicesResultT<Op, std::size_t> Run(Op&& op, std::size_t i) { - switch (i) { - case 0: - return PickCase<Op, 0, EndIndex>::Run(absl::forward<Op>(op)); - case 1: - return PickCase<Op, 1, EndIndex>::Run(absl::forward<Op>(op)); - case 2: - return PickCase<Op, 2, EndIndex>::Run(absl::forward<Op>(op)); - case 3: - return PickCase<Op, 3, EndIndex>::Run(absl::forward<Op>(op)); - case 4: - return PickCase<Op, 4, EndIndex>::Run(absl::forward<Op>(op)); - case 5: - return PickCase<Op, 5, EndIndex>::Run(absl::forward<Op>(op)); - case 6: - return PickCase<Op, 6, EndIndex>::Run(absl::forward<Op>(op)); - case 7: - return PickCase<Op, 7, EndIndex>::Run(absl::forward<Op>(op)); - case 8: - return PickCase<Op, 8, EndIndex>::Run(absl::forward<Op>(op)); - case 9: - return PickCase<Op, 9, EndIndex>::Run(absl::forward<Op>(op)); - case 10: - return PickCase<Op, 10, EndIndex>::Run(absl::forward<Op>(op)); - case 11: - return PickCase<Op, 11, EndIndex>::Run(absl::forward<Op>(op)); - case 12: - return PickCase<Op, 12, EndIndex>::Run(absl::forward<Op>(op)); - case 13: - return PickCase<Op, 13, EndIndex>::Run(absl::forward<Op>(op)); - case 14: - return PickCase<Op, 14, EndIndex>::Run(absl::forward<Op>(op)); - case 15: - return PickCase<Op, 15, EndIndex>::Run(absl::forward<Op>(op)); - case 16: - return PickCase<Op, 16, EndIndex>::Run(absl::forward<Op>(op)); - case 17: - return PickCase<Op, 17, EndIndex>::Run(absl::forward<Op>(op)); - case 18: - return PickCase<Op, 18, EndIndex>::Run(absl::forward<Op>(op)); - case 19: - return PickCase<Op, 19, EndIndex>::Run(absl::forward<Op>(op)); - case 20: - return PickCase<Op, 20, EndIndex>::Run(absl::forward<Op>(op)); - case 21: - return PickCase<Op, 21, EndIndex>::Run(absl::forward<Op>(op)); - case 22: - return PickCase<Op, 22, EndIndex>::Run(absl::forward<Op>(op)); - case 23: - return PickCase<Op, 23, EndIndex>::Run(absl::forward<Op>(op)); - case 24: - return PickCase<Op, 24, EndIndex>::Run(absl::forward<Op>(op)); - case 25: - return PickCase<Op, 25, EndIndex>::Run(absl::forward<Op>(op)); - case 26: - return PickCase<Op, 26, EndIndex>::Run(absl::forward<Op>(op)); - case 27: - return PickCase<Op, 27, EndIndex>::Run(absl::forward<Op>(op)); - case 28: - return PickCase<Op, 28, EndIndex>::Run(absl::forward<Op>(op)); - case 29: - return PickCase<Op, 29, EndIndex>::Run(absl::forward<Op>(op)); - case 30: - return PickCase<Op, 30, EndIndex>::Run(absl::forward<Op>(op)); - case 31: - return PickCase<Op, 31, EndIndex>::Run(absl::forward<Op>(op)); - case 32: - return PickCase<Op, 32, EndIndex>::Run(absl::forward<Op>(op)); - default: - ABSL_ASSERT(i == variant_npos); - return absl::base_internal::invoke(absl::forward<Op>(op), NPos()); - } - } -}; - -template <std::size_t... EndIndices> -struct VisitIndicesFallback { - template <class Op, class... SizeT> - static VisitIndicesResultT<Op, SizeT...> Run(Op&& op, SizeT... indices) { - return AccessSimpleArray( - MakeVisitationMatrix<VisitIndicesResultT<Op, SizeT...>, Op, - index_sequence<(EndIndices + 1)...>, - index_sequence<>>::Run(), - (indices + 1)...)(absl::forward<Op>(op)); - } -}; - -// Take an N-dimensional series of indices and convert them into a single index -// without loss of information. The purpose of this is to be able to convert an -// N-ary visit operation into a single switch statement. -template <std::size_t...> -struct FlattenIndices; - -template <std::size_t HeadSize, std::size_t... TailSize> -struct FlattenIndices<HeadSize, TailSize...> { - template<class... SizeType> - static constexpr std::size_t Run(std::size_t head, SizeType... tail) { - return head + HeadSize * FlattenIndices<TailSize...>::Run(tail...); - } -}; - -template <> -struct FlattenIndices<> { - static constexpr std::size_t Run() { return 0; } -}; - -// Take a single "flattened" index (flattened by FlattenIndices) and determine -// the value of the index of one of the logically represented dimensions. -template <std::size_t I, std::size_t IndexToGet, std::size_t HeadSize, - std::size_t... TailSize> -struct UnflattenIndex { - static constexpr std::size_t value = - UnflattenIndex<I / HeadSize, IndexToGet - 1, TailSize...>::value; -}; - -template <std::size_t I, std::size_t HeadSize, std::size_t... TailSize> -struct UnflattenIndex<I, 0, HeadSize, TailSize...> { - static constexpr std::size_t value = (I % HeadSize); -}; - -// The backend for converting an N-ary visit operation into a unary visit. -template <class IndexSequence, std::size_t... EndIndices> -struct VisitIndicesVariadicImpl; - -template <std::size_t... N, std::size_t... EndIndices> -struct VisitIndicesVariadicImpl<absl::index_sequence<N...>, EndIndices...> { - // A type that can take an N-ary function object and converts it to a unary - // function object that takes a single, flattened index, and "unflattens" it - // into its individual dimensions when forwarding to the wrapped object. - template <class Op> - struct FlattenedOp { - template <std::size_t I> - VisitIndicesResultT<Op, decltype(EndIndices)...> operator()( - SizeT<I> /*index*/) && { - return base_internal::invoke( - absl::forward<Op>(op), - SizeT<UnflattenIndex<I, N, (EndIndices + 1)...>::value - - std::size_t{1}>()...); - } - - Op&& op; - }; - - template <class Op, class... SizeType> - static VisitIndicesResultT<Op, decltype(EndIndices)...> Run( - Op&& op, SizeType... i) { - return VisitIndicesSwitch<NumCasesOfSwitch<EndIndices...>::value>::Run( - FlattenedOp<Op>{absl::forward<Op>(op)}, - FlattenIndices<(EndIndices + std::size_t{1})...>::Run( - (i + std::size_t{1})...)); - } -}; - -template <std::size_t... EndIndices> -struct VisitIndicesVariadic - : VisitIndicesVariadicImpl<absl::make_index_sequence<sizeof...(EndIndices)>, - EndIndices...> {}; - -// This implementation will flatten N-ary visit operations into a single switch -// statement when the number of cases would be less than our maximum specified -// switch-statement size. -// TODO(calabrese) -// Based on benchmarks, determine whether the function table approach actually -// does optimize better than a chain of switch statements and possibly update -// the implementation accordingly. Also consider increasing the maximum switch -// size. -template <std::size_t... EndIndices> -struct VisitIndices - : absl::conditional_t<(NumCasesOfSwitch<EndIndices...>::value <= - MaxUnrolledVisitCases), - VisitIndicesVariadic<EndIndices...>, - VisitIndicesFallback<EndIndices...>> {}; - -template <std::size_t EndIndex> -struct VisitIndices<EndIndex> - : absl::conditional_t<(EndIndex <= MaxUnrolledVisitCases), - VisitIndicesSwitch<EndIndex>, - VisitIndicesFallback<EndIndex>> {}; - -// Suppress bogus warning on MSVC: MSVC complains that the `reinterpret_cast` -// below is returning the address of a temporary or local object. -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4172) -#endif // _MSC_VER - -// TODO(calabrese) std::launder -// TODO(calabrese) constexpr -// NOTE: DO NOT REMOVE the `inline` keyword as it is necessary to work around a -// MSVC bug. See https://github.com/abseil/abseil-cpp/issues/129 for details. -template <class Self, std::size_t I> -inline VariantAccessResult<I, Self> AccessUnion(Self&& self, SizeT<I> /*i*/) { - return reinterpret_cast<VariantAccessResult<I, Self>>(self); -} - -#ifdef _MSC_VER -#pragma warning(pop) -#endif // _MSC_VER - -template <class T> -void DeducedDestroy(T& self) { // NOLINT - self.~T(); -} - -// NOTE: This type exists as a single entity for variant and its bases to -// befriend. It contains helper functionality that manipulates the state of the -// variant, such as the implementation of things like assignment and emplace -// operations. -struct VariantCoreAccess { - template <class VariantType> - static typename VariantType::Variant& Derived(VariantType& self) { // NOLINT - return static_cast<typename VariantType::Variant&>(self); - } - - template <class VariantType> - static const typename VariantType::Variant& Derived( - const VariantType& self) { // NOLINT - return static_cast<const typename VariantType::Variant&>(self); - } - - template <class VariantType> - static void Destroy(VariantType& self) { // NOLINT - Derived(self).destroy(); - self.index_ = absl::variant_npos; - } - - template <class Variant> - static void SetIndex(Variant& self, std::size_t i) { // NOLINT - self.index_ = i; - } - - template <class Variant> - static void InitFrom(Variant& self, Variant&& other) { // NOLINT - VisitIndices<absl::variant_size<Variant>::value>::Run( - InitFromVisitor<Variant, Variant&&>{&self, - std::forward<Variant>(other)}, - other.index()); - self.index_ = other.index(); - } - - // Access a variant alternative, assuming the index is correct. - template <std::size_t I, class Variant> - static VariantAccessResult<I, Variant> Access(Variant&& self) { - // This cast instead of invocation of AccessUnion with an rvalue is a - // workaround for msvc. Without this there is a runtime failure when dealing - // with rvalues. - // TODO(calabrese) Reduce test case and find a simpler workaround. - return static_cast<VariantAccessResult<I, Variant>>( - variant_internal::AccessUnion(self.state_, SizeT<I>())); - } - - // Access a variant alternative, throwing if the index is incorrect. - template <std::size_t I, class Variant> - static VariantAccessResult<I, Variant> CheckedAccess(Variant&& self) { - if (ABSL_PREDICT_FALSE(self.index_ != I)) { - TypedThrowBadVariantAccess<VariantAccessResult<I, Variant>>(); - } - - return Access<I>(absl::forward<Variant>(self)); - } - - // The implementation of the move-assignment operation for a variant. - template <class VType> - struct MoveAssignVisitor { - using DerivedType = typename VType::Variant; - template <std::size_t NewIndex> - void operator()(SizeT<NewIndex> /*new_i*/) const { - if (left->index_ == NewIndex) { - Access<NewIndex>(*left) = std::move(Access<NewIndex>(*right)); - } else { - Derived(*left).template emplace<NewIndex>( - std::move(Access<NewIndex>(*right))); - } - } - - void operator()(SizeT<absl::variant_npos> /*new_i*/) const { - Destroy(*left); - } - - VType* left; - VType* right; - }; - - template <class VType> - static MoveAssignVisitor<VType> MakeMoveAssignVisitor(VType* left, - VType* other) { - return {left, other}; - } - - // The implementation of the assignment operation for a variant. - template <class VType> - struct CopyAssignVisitor { - using DerivedType = typename VType::Variant; - template <std::size_t NewIndex> - void operator()(SizeT<NewIndex> /*new_i*/) const { - using New = - typename absl::variant_alternative<NewIndex, DerivedType>::type; - - if (left->index_ == NewIndex) { - Access<NewIndex>(*left) = Access<NewIndex>(*right); - } else if (std::is_nothrow_copy_constructible<New>::value || - !std::is_nothrow_move_constructible<New>::value) { - Derived(*left).template emplace<NewIndex>(Access<NewIndex>(*right)); - } else { - Derived(*left) = DerivedType(Derived(*right)); - } - } - - void operator()(SizeT<absl::variant_npos> /*new_i*/) const { - Destroy(*left); - } - - VType* left; - const VType* right; - }; - - template <class VType> - static CopyAssignVisitor<VType> MakeCopyAssignVisitor(VType* left, - const VType& other) { - return {left, &other}; - } - - // The implementation of conversion-assignment operations for variant. - template <class Left, class QualifiedNew> - struct ConversionAssignVisitor { - using NewIndex = - variant_internal::IndexOfConstructedType<Left, QualifiedNew>; - - void operator()(SizeT<NewIndex::value> /*old_i*/ - ) const { - Access<NewIndex::value>(*left) = absl::forward<QualifiedNew>(other); - } - - template <std::size_t OldIndex> - void operator()(SizeT<OldIndex> /*old_i*/ - ) const { - using New = - typename absl::variant_alternative<NewIndex::value, Left>::type; - if (std::is_nothrow_constructible<New, QualifiedNew>::value || - !std::is_nothrow_move_constructible<New>::value) { - left->template emplace<NewIndex::value>( - absl::forward<QualifiedNew>(other)); - } else { - // the standard says "equivalent to - // operator=(variant(std::forward<T>(t)))", but we use `emplace` here - // because the variant's move assignment operator could be deleted. - left->template emplace<NewIndex::value>( - New(absl::forward<QualifiedNew>(other))); - } - } - - Left* left; - QualifiedNew&& other; - }; - - template <class Left, class QualifiedNew> - static ConversionAssignVisitor<Left, QualifiedNew> - MakeConversionAssignVisitor(Left* left, QualifiedNew&& qual) { - return {left, absl::forward<QualifiedNew>(qual)}; - } - - // Backend for operations for `emplace()` which destructs `*self` then - // construct a new alternative with `Args...`. - template <std::size_t NewIndex, class Self, class... Args> - static typename absl::variant_alternative<NewIndex, Self>::type& Replace( - Self* self, Args&&... args) { - Destroy(*self); - using New = typename absl::variant_alternative<NewIndex, Self>::type; - New* const result = ::new (static_cast<void*>(&self->state_)) - New(absl::forward<Args>(args)...); - self->index_ = NewIndex; - return *result; - } - - template <class LeftVariant, class QualifiedRightVariant> - struct InitFromVisitor { - template <std::size_t NewIndex> - void operator()(SizeT<NewIndex> /*new_i*/) const { - using Alternative = - typename variant_alternative<NewIndex, LeftVariant>::type; - ::new (static_cast<void*>(&left->state_)) Alternative( - Access<NewIndex>(std::forward<QualifiedRightVariant>(right))); - } - - void operator()(SizeT<absl::variant_npos> /*new_i*/) const { - // This space intentionally left blank. - } - LeftVariant* left; - QualifiedRightVariant&& right; - }; -}; - -template <class Expected, class... T> -struct IndexOfImpl; - -template <class Expected> -struct IndexOfImpl<Expected> { - using IndexFromEnd = SizeT<0>; - using MatchedIndexFromEnd = IndexFromEnd; - using MultipleMatches = std::false_type; -}; - -template <class Expected, class Head, class... Tail> -struct IndexOfImpl<Expected, Head, Tail...> : IndexOfImpl<Expected, Tail...> { - using IndexFromEnd = - SizeT<IndexOfImpl<Expected, Tail...>::IndexFromEnd::value + 1>; -}; - -template <class Expected, class... Tail> -struct IndexOfImpl<Expected, Expected, Tail...> - : IndexOfImpl<Expected, Tail...> { - using IndexFromEnd = - SizeT<IndexOfImpl<Expected, Tail...>::IndexFromEnd::value + 1>; - using MatchedIndexFromEnd = IndexFromEnd; - using MultipleMatches = std::integral_constant< - bool, IndexOfImpl<Expected, Tail...>::MatchedIndexFromEnd::value != 0>; -}; - -template <class Expected, class... Types> -struct IndexOfMeta { - using Results = IndexOfImpl<Expected, Types...>; - static_assert(!Results::MultipleMatches::value, - "Attempted to access a variant by specifying a type that " - "matches more than one alternative."); - static_assert(Results::MatchedIndexFromEnd::value != 0, - "Attempted to access a variant by specifying a type that does " - "not match any alternative."); - using type = SizeT<sizeof...(Types) - Results::MatchedIndexFromEnd::value>; -}; - -template <class Expected, class... Types> -using IndexOf = typename IndexOfMeta<Expected, Types...>::type; - -template <class Variant, class T, std::size_t CurrIndex> -struct UnambiguousIndexOfImpl; - -// Terminating case encountered once we've checked all of the alternatives -template <class T, std::size_t CurrIndex> -struct UnambiguousIndexOfImpl<variant<>, T, CurrIndex> : SizeT<CurrIndex> {}; - -// Case where T is not Head -template <class Head, class... Tail, class T, std::size_t CurrIndex> -struct UnambiguousIndexOfImpl<variant<Head, Tail...>, T, CurrIndex> - : UnambiguousIndexOfImpl<variant<Tail...>, T, CurrIndex + 1>::type {}; - -// Case where T is Head -template <class Head, class... Tail, std::size_t CurrIndex> -struct UnambiguousIndexOfImpl<variant<Head, Tail...>, Head, CurrIndex> - : SizeT<UnambiguousIndexOfImpl<variant<Tail...>, Head, 0>::value == - sizeof...(Tail) - ? CurrIndex - : CurrIndex + sizeof...(Tail) + 1> {}; - -template <class Variant, class T> -struct UnambiguousIndexOf; - -struct NoMatch { - struct type {}; -}; - -template <class... Alts, class T> -struct UnambiguousIndexOf<variant<Alts...>, T> - : std::conditional<UnambiguousIndexOfImpl<variant<Alts...>, T, 0>::value != - sizeof...(Alts), - UnambiguousIndexOfImpl<variant<Alts...>, T, 0>, - NoMatch>::type::type {}; - -template <class T, std::size_t /*Dummy*/> -using UnambiguousTypeOfImpl = T; - -template <class Variant, class T> -using UnambiguousTypeOfT = - UnambiguousTypeOfImpl<T, UnambiguousIndexOf<Variant, T>::value>; - -template <class H, class... T> -class VariantStateBase; - -// This is an implementation of the "imaginary function" that is described in -// [variant.ctor] -// It is used in order to determine which alternative to construct during -// initialization from some type T. -template <class Variant, std::size_t I = 0> -struct ImaginaryFun; - -template <std::size_t I> -struct ImaginaryFun<variant<>, I> { - static void Run() = delete; -}; - -template <class H, class... T, std::size_t I> -struct ImaginaryFun<variant<H, T...>, I> : ImaginaryFun<variant<T...>, I + 1> { - using ImaginaryFun<variant<T...>, I + 1>::Run; - - // NOTE: const& and && are used instead of by-value due to lack of guaranteed - // move elision of C++17. This may have other minor differences, but tests - // pass. - static SizeT<I> Run(const H&, SizeT<I>); - static SizeT<I> Run(H&&, SizeT<I>); -}; - -// The following metafunctions are used in constructor and assignment -// constraints. -template <class Self, class T> -struct IsNeitherSelfNorInPlace : std::true_type {}; - -template <class Self> -struct IsNeitherSelfNorInPlace<Self, Self> : std::false_type {}; - -template <class Self, class T> -struct IsNeitherSelfNorInPlace<Self, in_place_type_t<T>> : std::false_type {}; - -template <class Self, std::size_t I> -struct IsNeitherSelfNorInPlace<Self, in_place_index_t<I>> : std::false_type {}; - -template <class Variant, class T, class = void> -struct ConversionIsPossibleImpl : std::false_type {}; - -template <class Variant, class T> -struct ConversionIsPossibleImpl< - Variant, T, - void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {}))>> - : std::true_type {}; - -template <class Variant, class T> -struct ConversionIsPossible : ConversionIsPossibleImpl<Variant, T>::type {}; - -template <class Variant, class T> -struct IndexOfConstructedType< - Variant, T, - void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {}))>> - : decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {})) {}; - -template <std::size_t... Is> -struct ContainsVariantNPos - : absl::negation<std::is_same< // NOLINT - absl::integer_sequence<bool, 0 <= Is...>, - absl::integer_sequence<bool, Is != absl::variant_npos...>>> {}; - -template <class Op, class... QualifiedVariants> -using RawVisitResult = - absl::result_of_t<Op(VariantAccessResult<0, QualifiedVariants>...)>; - -// NOTE: The spec requires that all return-paths yield the same type and is not -// SFINAE-friendly, so we can deduce the return type by examining the first -// result. If it's not callable, then we get an error, but are compliant and -// fast to compile. -// TODO(calabrese) Possibly rewrite in a way that yields better compile errors -// at the cost of longer compile-times. -template <class Op, class... QualifiedVariants> -struct VisitResultImpl { - using type = - absl::result_of_t<Op(VariantAccessResult<0, QualifiedVariants>...)>; -}; - -// Done in two steps intentionally so that we don't cause substitution to fail. -template <class Op, class... QualifiedVariants> -using VisitResult = typename VisitResultImpl<Op, QualifiedVariants...>::type; - -template <class Op, class... QualifiedVariants> -struct PerformVisitation { - using ReturnType = VisitResult<Op, QualifiedVariants...>; - - template <std::size_t... Is> - constexpr ReturnType operator()(SizeT<Is>... indices) const { - return Run(typename ContainsVariantNPos<Is...>::type{}, - absl::index_sequence_for<QualifiedVariants...>(), indices...); - } - - template <std::size_t... TupIs, std::size_t... Is> - constexpr ReturnType Run(std::false_type /*has_valueless*/, - index_sequence<TupIs...>, SizeT<Is>...) const { - static_assert( - std::is_same<ReturnType, - absl::result_of_t<Op(VariantAccessResult< - Is, QualifiedVariants>...)>>::value, - "All visitation overloads must have the same return type."); - return absl::base_internal::invoke( - absl::forward<Op>(op), - VariantCoreAccess::Access<Is>( - absl::forward<QualifiedVariants>(std::get<TupIs>(variant_tup)))...); - } - - template <std::size_t... TupIs, std::size_t... Is> - [[noreturn]] ReturnType Run(std::true_type /*has_valueless*/, - index_sequence<TupIs...>, SizeT<Is>...) const { - absl::variant_internal::ThrowBadVariantAccess(); - } - - // TODO(calabrese) Avoid using a tuple, which causes lots of instantiations - // Attempts using lambda variadic captures fail on current GCC. - std::tuple<QualifiedVariants&&...> variant_tup; - Op&& op; -}; - -template <class... T> -union Union; - -// We want to allow for variant<> to be trivial. For that, we need the default -// constructor to be trivial, which means we can't define it ourselves. -// Instead, we use a non-default constructor that takes NoopConstructorTag -// that doesn't affect the triviality of the types. -struct NoopConstructorTag {}; - -template <std::size_t I> -struct EmplaceTag {}; - -template <> -union Union<> { - constexpr explicit Union(NoopConstructorTag) noexcept {} -}; - -// Suppress bogus warning on MSVC: MSVC complains that Union<T...> has a defined -// deleted destructor from the `std::is_destructible` check below. -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4624) -#endif // _MSC_VER - -template <class Head, class... Tail> -union Union<Head, Tail...> { - using TailUnion = Union<Tail...>; - - explicit constexpr Union(NoopConstructorTag /*tag*/) noexcept - : tail(NoopConstructorTag()) {} - - template <class... P> - explicit constexpr Union(EmplaceTag<0>, P&&... args) - : head(absl::forward<P>(args)...) {} - - template <std::size_t I, class... P> - explicit constexpr Union(EmplaceTag<I>, P&&... args) - : tail(EmplaceTag<I - 1>{}, absl::forward<P>(args)...) {} - - Head head; - TailUnion tail; -}; - -#ifdef _MSC_VER -#pragma warning(pop) -#endif // _MSC_VER - -// TODO(calabrese) Just contain a Union in this union (certain configs fail). -template <class... T> -union DestructibleUnionImpl; - -template <> -union DestructibleUnionImpl<> { - constexpr explicit DestructibleUnionImpl(NoopConstructorTag) noexcept {} -}; - -template <class Head, class... Tail> -union DestructibleUnionImpl<Head, Tail...> { - using TailUnion = DestructibleUnionImpl<Tail...>; - - explicit constexpr DestructibleUnionImpl(NoopConstructorTag /*tag*/) noexcept - : tail(NoopConstructorTag()) {} - - template <class... P> - explicit constexpr DestructibleUnionImpl(EmplaceTag<0>, P&&... args) - : head(absl::forward<P>(args)...) {} - - template <std::size_t I, class... P> - explicit constexpr DestructibleUnionImpl(EmplaceTag<I>, P&&... args) - : tail(EmplaceTag<I - 1>{}, absl::forward<P>(args)...) {} - - ~DestructibleUnionImpl() {} - - Head head; - TailUnion tail; -}; - -// This union type is destructible even if one or more T are not trivially -// destructible. In the case that all T are trivially destructible, then so is -// this resultant type. -template <class... T> -using DestructibleUnion = - absl::conditional_t<std::is_destructible<Union<T...>>::value, Union<T...>, - DestructibleUnionImpl<T...>>; - -// Deepest base, containing the actual union and the discriminator -template <class H, class... T> -class VariantStateBase { - protected: - using Variant = variant<H, T...>; - - template <class LazyH = H, - class ConstructibleH = absl::enable_if_t< - std::is_default_constructible<LazyH>::value, LazyH>> - constexpr VariantStateBase() noexcept( - std::is_nothrow_default_constructible<ConstructibleH>::value) - : state_(EmplaceTag<0>()), index_(0) {} - - template <std::size_t I, class... P> - explicit constexpr VariantStateBase(EmplaceTag<I> tag, P&&... args) - : state_(tag, absl::forward<P>(args)...), index_(I) {} - - explicit constexpr VariantStateBase(NoopConstructorTag) - : state_(NoopConstructorTag()), index_(variant_npos) {} - - void destroy() {} // Does nothing (shadowed in child if non-trivial) - - DestructibleUnion<H, T...> state_; - std::size_t index_; -}; - -using absl::internal::identity; - -// OverloadSet::Overload() is a unary function which is overloaded to -// take any of the element types of the variant, by reference-to-const. -// The return type of the overload on T is identity<T>, so that you -// can statically determine which overload was called. -// -// Overload() is not defined, so it can only be called in unevaluated -// contexts. -template <typename... Ts> -struct OverloadSet; - -template <typename T, typename... Ts> -struct OverloadSet<T, Ts...> : OverloadSet<Ts...> { - using Base = OverloadSet<Ts...>; - static identity<T> Overload(const T&); - using Base::Overload; -}; - -template <> -struct OverloadSet<> { - // For any case not handled above. - static void Overload(...); -}; - -template <class T> -using LessThanResult = decltype(std::declval<T>() < std::declval<T>()); - -template <class T> -using GreaterThanResult = decltype(std::declval<T>() > std::declval<T>()); - -template <class T> -using LessThanOrEqualResult = decltype(std::declval<T>() <= std::declval<T>()); - -template <class T> -using GreaterThanOrEqualResult = - decltype(std::declval<T>() >= std::declval<T>()); - -template <class T> -using EqualResult = decltype(std::declval<T>() == std::declval<T>()); - -template <class T> -using NotEqualResult = decltype(std::declval<T>() != std::declval<T>()); - -using type_traits_internal::is_detected_convertible; - -template <class... T> -using RequireAllHaveEqualT = absl::enable_if_t< - absl::conjunction<is_detected_convertible<bool, EqualResult, T>...>::value, - bool>; - -template <class... T> -using RequireAllHaveNotEqualT = - absl::enable_if_t<absl::conjunction<is_detected_convertible< - bool, NotEqualResult, T>...>::value, - bool>; - -template <class... T> -using RequireAllHaveLessThanT = - absl::enable_if_t<absl::conjunction<is_detected_convertible< - bool, LessThanResult, T>...>::value, - bool>; - -template <class... T> -using RequireAllHaveLessThanOrEqualT = - absl::enable_if_t<absl::conjunction<is_detected_convertible< - bool, LessThanOrEqualResult, T>...>::value, - bool>; - -template <class... T> -using RequireAllHaveGreaterThanOrEqualT = - absl::enable_if_t<absl::conjunction<is_detected_convertible< - bool, GreaterThanOrEqualResult, T>...>::value, - bool>; - -template <class... T> -using RequireAllHaveGreaterThanT = - absl::enable_if_t<absl::conjunction<is_detected_convertible< - bool, GreaterThanResult, T>...>::value, - bool>; - -// Helper template containing implementations details of variant that can't go -// in the private section. For convenience, this takes the variant type as a -// single template parameter. -template <typename T> -struct VariantHelper; - -template <typename... Ts> -struct VariantHelper<variant<Ts...>> { - // Type metafunction which returns the element type selected if - // OverloadSet::Overload() is well-formed when called with argument type U. - template <typename U> - using BestMatch = decltype( - variant_internal::OverloadSet<Ts...>::Overload(std::declval<U>())); - - // Type metafunction which returns true if OverloadSet::Overload() is - // well-formed when called with argument type U. - // CanAccept can't be just an alias because there is a MSVC bug on parameter - // pack expansion involving decltype. - template <typename U> - struct CanAccept : - std::integral_constant<bool, !std::is_void<BestMatch<U>>::value> {}; - - // Type metafunction which returns true if Other is an instantiation of - // variant, and variants's converting constructor from Other will be - // well-formed. We will use this to remove constructors that would be - // ill-formed from the overload set. - template <typename Other> - struct CanConvertFrom; - - template <typename... Us> - struct CanConvertFrom<variant<Us...>> - : public absl::conjunction<CanAccept<Us>...> {}; -}; - -// A type with nontrivial copy ctor and trivial move ctor. -struct TrivialMoveOnly { - TrivialMoveOnly(TrivialMoveOnly&&) = default; -}; - -// Trait class to detect whether a type is trivially move constructible. -// A union's defaulted copy/move constructor is deleted if any variant member's -// copy/move constructor is nontrivial. -template <typename T> -struct IsTriviallyMoveConstructible: - std::is_move_constructible<Union<T, TrivialMoveOnly>> {}; - -// To guarantee triviality of all special-member functions that can be trivial, -// we use a chain of conditional bases for each one. -// The order of inheritance of bases from child to base are logically: -// -// variant -// VariantCopyAssignBase -// VariantMoveAssignBase -// VariantCopyBase -// VariantMoveBase -// VariantStateBaseDestructor -// VariantStateBase -// -// Note that there is a separate branch at each base that is dependent on -// whether or not that corresponding special-member-function can be trivial in -// the resultant variant type. - -template <class... T> -class VariantStateBaseDestructorNontrivial; - -template <class... T> -class VariantMoveBaseNontrivial; - -template <class... T> -class VariantCopyBaseNontrivial; - -template <class... T> -class VariantMoveAssignBaseNontrivial; - -template <class... T> -class VariantCopyAssignBaseNontrivial; - -// Base that is dependent on whether or not the destructor can be trivial. -template <class... T> -using VariantStateBaseDestructor = - absl::conditional_t<std::is_destructible<Union<T...>>::value, - VariantStateBase<T...>, - VariantStateBaseDestructorNontrivial<T...>>; - -// Base that is dependent on whether or not the move-constructor can be -// implicitly generated by the compiler (trivial or deleted). -// Previously we were using `std::is_move_constructible<Union<T...>>` to check -// whether all Ts have trivial move constructor, but it ran into a GCC bug: -// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84866 -// So we have to use a different approach (i.e. `HasTrivialMoveConstructor`) to -// work around the bug. -template <class... T> -using VariantMoveBase = absl::conditional_t< - absl::disjunction< - absl::negation<absl::conjunction<std::is_move_constructible<T>...>>, - absl::conjunction<IsTriviallyMoveConstructible<T>...>>::value, - VariantStateBaseDestructor<T...>, VariantMoveBaseNontrivial<T...>>; - -// Base that is dependent on whether or not the copy-constructor can be trivial. -template <class... T> -using VariantCopyBase = absl::conditional_t< - absl::disjunction< - absl::negation<absl::conjunction<std::is_copy_constructible<T>...>>, - std::is_copy_constructible<Union<T...>>>::value, - VariantMoveBase<T...>, VariantCopyBaseNontrivial<T...>>; - -// Base that is dependent on whether or not the move-assign can be trivial. -template <class... T> -using VariantMoveAssignBase = absl::conditional_t< - absl::disjunction< - absl::conjunction<absl::is_move_assignable<Union<T...>>, - std::is_move_constructible<Union<T...>>, - std::is_destructible<Union<T...>>>, - absl::negation<absl::conjunction<std::is_move_constructible<T>..., - // Note: We're not qualifying this with - // absl:: because it doesn't compile - // under MSVC. - is_move_assignable<T>...>>>::value, - VariantCopyBase<T...>, VariantMoveAssignBaseNontrivial<T...>>; - -// Base that is dependent on whether or not the copy-assign can be trivial. -template <class... T> -using VariantCopyAssignBase = absl::conditional_t< - absl::disjunction< - absl::conjunction<absl::is_copy_assignable<Union<T...>>, - std::is_copy_constructible<Union<T...>>, - std::is_destructible<Union<T...>>>, - absl::negation<absl::conjunction<std::is_copy_constructible<T>..., - // Note: We're not qualifying this with - // absl:: because it doesn't compile - // under MSVC. - is_copy_assignable<T>...>>>::value, - VariantMoveAssignBase<T...>, VariantCopyAssignBaseNontrivial<T...>>; - -template <class... T> -using VariantBase = VariantCopyAssignBase<T...>; - -template <class... T> -class VariantStateBaseDestructorNontrivial : protected VariantStateBase<T...> { - private: - using Base = VariantStateBase<T...>; - - protected: - using Base::Base; - - VariantStateBaseDestructorNontrivial() = default; - VariantStateBaseDestructorNontrivial(VariantStateBaseDestructorNontrivial&&) = - default; - VariantStateBaseDestructorNontrivial( - const VariantStateBaseDestructorNontrivial&) = default; - VariantStateBaseDestructorNontrivial& operator=( - VariantStateBaseDestructorNontrivial&&) = default; - VariantStateBaseDestructorNontrivial& operator=( - const VariantStateBaseDestructorNontrivial&) = default; - - struct Destroyer { - template <std::size_t I> - void operator()(SizeT<I> i) const { - using Alternative = - typename absl::variant_alternative<I, variant<T...>>::type; - variant_internal::AccessUnion(self->state_, i).~Alternative(); - } - - void operator()(SizeT<absl::variant_npos> /*i*/) const { - // This space intentionally left blank - } - - VariantStateBaseDestructorNontrivial* self; - }; - - void destroy() { VisitIndices<sizeof...(T)>::Run(Destroyer{this}, index_); } - - ~VariantStateBaseDestructorNontrivial() { destroy(); } - - protected: - using Base::index_; - using Base::state_; -}; - -template <class... T> -class VariantMoveBaseNontrivial : protected VariantStateBaseDestructor<T...> { - private: - using Base = VariantStateBaseDestructor<T...>; - - protected: - using Base::Base; - - struct Construct { - template <std::size_t I> - void operator()(SizeT<I> i) const { - using Alternative = - typename absl::variant_alternative<I, variant<T...>>::type; - ::new (static_cast<void*>(&self->state_)) Alternative( - variant_internal::AccessUnion(absl::move(other->state_), i)); - } - - void operator()(SizeT<absl::variant_npos> /*i*/) const {} - - VariantMoveBaseNontrivial* self; - VariantMoveBaseNontrivial* other; - }; - - VariantMoveBaseNontrivial() = default; - VariantMoveBaseNontrivial(VariantMoveBaseNontrivial&& other) noexcept( - absl::conjunction<std::is_nothrow_move_constructible<T>...>::value) - : Base(NoopConstructorTag()) { - VisitIndices<sizeof...(T)>::Run(Construct{this, &other}, other.index_); - index_ = other.index_; - } - - VariantMoveBaseNontrivial(VariantMoveBaseNontrivial const&) = default; - - VariantMoveBaseNontrivial& operator=(VariantMoveBaseNontrivial&&) = default; - VariantMoveBaseNontrivial& operator=(VariantMoveBaseNontrivial const&) = - default; - - protected: - using Base::index_; - using Base::state_; -}; - -template <class... T> -class VariantCopyBaseNontrivial : protected VariantMoveBase<T...> { - private: - using Base = VariantMoveBase<T...>; - - protected: - using Base::Base; - - VariantCopyBaseNontrivial() = default; - VariantCopyBaseNontrivial(VariantCopyBaseNontrivial&&) = default; - - struct Construct { - template <std::size_t I> - void operator()(SizeT<I> i) const { - using Alternative = - typename absl::variant_alternative<I, variant<T...>>::type; - ::new (static_cast<void*>(&self->state_)) - Alternative(variant_internal::AccessUnion(other->state_, i)); - } - - void operator()(SizeT<absl::variant_npos> /*i*/) const {} - - VariantCopyBaseNontrivial* self; - const VariantCopyBaseNontrivial* other; - }; - - VariantCopyBaseNontrivial(VariantCopyBaseNontrivial const& other) - : Base(NoopConstructorTag()) { - VisitIndices<sizeof...(T)>::Run(Construct{this, &other}, other.index_); - index_ = other.index_; - } - - VariantCopyBaseNontrivial& operator=(VariantCopyBaseNontrivial&&) = default; - VariantCopyBaseNontrivial& operator=(VariantCopyBaseNontrivial const&) = - default; - - protected: - using Base::index_; - using Base::state_; -}; - -template <class... T> -class VariantMoveAssignBaseNontrivial : protected VariantCopyBase<T...> { - friend struct VariantCoreAccess; - - private: - using Base = VariantCopyBase<T...>; - - protected: - using Base::Base; - - VariantMoveAssignBaseNontrivial() = default; - VariantMoveAssignBaseNontrivial(VariantMoveAssignBaseNontrivial&&) = default; - VariantMoveAssignBaseNontrivial(const VariantMoveAssignBaseNontrivial&) = - default; - VariantMoveAssignBaseNontrivial& operator=( - VariantMoveAssignBaseNontrivial const&) = default; - - VariantMoveAssignBaseNontrivial& - operator=(VariantMoveAssignBaseNontrivial&& other) noexcept( - absl::conjunction<std::is_nothrow_move_constructible<T>..., - std::is_nothrow_move_assignable<T>...>::value) { - VisitIndices<sizeof...(T)>::Run( - VariantCoreAccess::MakeMoveAssignVisitor(this, &other), other.index_); - return *this; - } - - protected: - using Base::index_; - using Base::state_; -}; - -template <class... T> -class VariantCopyAssignBaseNontrivial : protected VariantMoveAssignBase<T...> { - friend struct VariantCoreAccess; - - private: - using Base = VariantMoveAssignBase<T...>; - - protected: - using Base::Base; - - VariantCopyAssignBaseNontrivial() = default; - VariantCopyAssignBaseNontrivial(VariantCopyAssignBaseNontrivial&&) = default; - VariantCopyAssignBaseNontrivial(const VariantCopyAssignBaseNontrivial&) = - default; - VariantCopyAssignBaseNontrivial& operator=( - VariantCopyAssignBaseNontrivial&&) = default; - - VariantCopyAssignBaseNontrivial& operator=( - const VariantCopyAssignBaseNontrivial& other) { - VisitIndices<sizeof...(T)>::Run( - VariantCoreAccess::MakeCopyAssignVisitor(this, other), other.index_); - return *this; - } - - protected: - using Base::index_; - using Base::state_; -}; - -//////////////////////////////////////// -// Visitors for Comparison Operations // -//////////////////////////////////////// - -template <class... Types> -struct EqualsOp { - const variant<Types...>* v; - const variant<Types...>* w; - - constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const { - return true; - } - - template <std::size_t I> - constexpr bool operator()(SizeT<I> /*v_i*/) const { - return VariantCoreAccess::Access<I>(*v) == VariantCoreAccess::Access<I>(*w); - } -}; - -template <class... Types> -struct NotEqualsOp { - const variant<Types...>* v; - const variant<Types...>* w; - - constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const { - return false; - } - - template <std::size_t I> - constexpr bool operator()(SizeT<I> /*v_i*/) const { - return VariantCoreAccess::Access<I>(*v) != VariantCoreAccess::Access<I>(*w); - } -}; - -template <class... Types> -struct LessThanOp { - const variant<Types...>* v; - const variant<Types...>* w; - - constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const { - return false; - } - - template <std::size_t I> - constexpr bool operator()(SizeT<I> /*v_i*/) const { - return VariantCoreAccess::Access<I>(*v) < VariantCoreAccess::Access<I>(*w); - } -}; - -template <class... Types> -struct GreaterThanOp { - const variant<Types...>* v; - const variant<Types...>* w; - - constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const { - return false; - } - - template <std::size_t I> - constexpr bool operator()(SizeT<I> /*v_i*/) const { - return VariantCoreAccess::Access<I>(*v) > VariantCoreAccess::Access<I>(*w); - } -}; - -template <class... Types> -struct LessThanOrEqualsOp { - const variant<Types...>* v; - const variant<Types...>* w; - - constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const { - return true; - } - - template <std::size_t I> - constexpr bool operator()(SizeT<I> /*v_i*/) const { - return VariantCoreAccess::Access<I>(*v) <= VariantCoreAccess::Access<I>(*w); - } -}; - -template <class... Types> -struct GreaterThanOrEqualsOp { - const variant<Types...>* v; - const variant<Types...>* w; - - constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const { - return true; - } - - template <std::size_t I> - constexpr bool operator()(SizeT<I> /*v_i*/) const { - return VariantCoreAccess::Access<I>(*v) >= VariantCoreAccess::Access<I>(*w); - } -}; - -// Precondition: v.index() == w.index(); -template <class... Types> -struct SwapSameIndex { - variant<Types...>* v; - variant<Types...>* w; - template <std::size_t I> - void operator()(SizeT<I>) const { - type_traits_internal::Swap(VariantCoreAccess::Access<I>(*v), - VariantCoreAccess::Access<I>(*w)); - } - - void operator()(SizeT<variant_npos>) const {} -}; - -// TODO(calabrese) do this from a different namespace for proper adl usage -template <class... Types> -struct Swap { - variant<Types...>* v; - variant<Types...>* w; - - void generic_swap() const { - variant<Types...> tmp(std::move(*w)); - VariantCoreAccess::Destroy(*w); - VariantCoreAccess::InitFrom(*w, std::move(*v)); - VariantCoreAccess::Destroy(*v); - VariantCoreAccess::InitFrom(*v, std::move(tmp)); - } - - void operator()(SizeT<absl::variant_npos> /*w_i*/) const { - if (!v->valueless_by_exception()) { - generic_swap(); - } - } - - template <std::size_t Wi> - void operator()(SizeT<Wi> /*w_i*/) { - if (v->index() == Wi) { - VisitIndices<sizeof...(Types)>::Run(SwapSameIndex<Types...>{v, w}, Wi); - } else { - generic_swap(); - } - } -}; - -template <typename Variant, typename = void, typename... Ts> -struct VariantHashBase { - VariantHashBase() = delete; - VariantHashBase(const VariantHashBase&) = delete; - VariantHashBase(VariantHashBase&&) = delete; - VariantHashBase& operator=(const VariantHashBase&) = delete; - VariantHashBase& operator=(VariantHashBase&&) = delete; -}; - -struct VariantHashVisitor { - template <typename T> - size_t operator()(const T& t) { - return std::hash<T>{}(t); - } -}; - -template <typename Variant, typename... Ts> -struct VariantHashBase<Variant, - absl::enable_if_t<absl::conjunction< - type_traits_internal::IsHashable<Ts>...>::value>, - Ts...> { - using argument_type = Variant; - using result_type = size_t; - size_t operator()(const Variant& var) const { - type_traits_internal::AssertHashEnabled<Ts...>(); - if (var.valueless_by_exception()) { - return 239799884; - } - size_t result = VisitIndices<variant_size<Variant>::value>::Run( - PerformVisitation<VariantHashVisitor, const Variant&>{ - std::forward_as_tuple(var), VariantHashVisitor{}}, - var.index()); - // Combine the index and the hash result in order to distinguish - // std::variant<int, int> holding the same value as different alternative. - return result ^ var.index(); - } -}; - -} // namespace variant_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // !defined(ABSL_USES_STD_VARIANT) -#endif // ABSL_TYPES_variant_internal_H_ |