diff options
-rw-r--r-- | CMake/AbseilDll.cmake | 5 | ||||
-rw-r--r-- | absl/types/BUILD.bazel | 38 | ||||
-rw-r--r-- | absl/types/CMakeLists.txt | 53 | ||||
-rw-r--r-- | absl/types/internal/conformance_aliases.h | 447 | ||||
-rw-r--r-- | absl/types/internal/conformance_archetype.h | 978 | ||||
-rw-r--r-- | absl/types/internal/conformance_profile.h | 933 | ||||
-rw-r--r-- | absl/types/internal/conformance_testing.h | 1386 | ||||
-rw-r--r-- | absl/types/internal/conformance_testing_helpers.h | 391 | ||||
-rw-r--r-- | absl/types/internal/conformance_testing_test.cc | 1556 | ||||
-rw-r--r-- | absl/types/internal/parentheses.h | 34 | ||||
-rw-r--r-- | absl/types/internal/transform_args.h | 246 |
11 files changed, 0 insertions, 6067 deletions
diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake index 1a20a84f..9024a06b 100644 --- a/CMake/AbseilDll.cmake +++ b/CMake/AbseilDll.cmake @@ -423,11 +423,6 @@ set(ABSL_INTERNAL_DLL_FILES "types/bad_variant_access.cc" "types/bad_variant_access.h" "types/compare.h" - "types/internal/conformance_aliases.h" - "types/internal/conformance_archetype.h" - "types/internal/conformance_profile.h" - "types/internal/parentheses.h" - "types/internal/transform_args.h" "types/internal/variant.h" "types/optional.h" "types/internal/optional.h" diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel index b57d3b9b..34f398bb 100644 --- a/absl/types/BUILD.bazel +++ b/absl/types/BUILD.bazel @@ -208,44 +208,6 @@ cc_test( ) cc_library( - name = "conformance_testing", - testonly = 1, - hdrs = [ - "internal/conformance_aliases.h", - "internal/conformance_archetype.h", - "internal/conformance_profile.h", - "internal/conformance_testing.h", - "internal/conformance_testing_helpers.h", - "internal/parentheses.h", - "internal/transform_args.h", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/algorithm:container", - "//absl/meta:type_traits", - "//absl/strings", - "//absl/utility", - "@com_google_googletest//:gtest", - ], -) - -cc_test( - name = "conformance_testing_test", - size = "small", - srcs = [ - "internal/conformance_testing_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":conformance_testing", - "//absl/meta:type_traits", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( name = "variant", srcs = ["internal/variant.h"], hdrs = ["variant.h"], diff --git a/absl/types/CMakeLists.txt b/absl/types/CMakeLists.txt index c0dcee79..1adf3c72 100644 --- a/absl/types/CMakeLists.txt +++ b/absl/types/CMakeLists.txt @@ -240,59 +240,6 @@ absl_cc_test( GTest::gmock_main ) -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - conformance_testing - HDRS - "internal/conformance_aliases.h" - "internal/conformance_archetype.h" - "internal/conformance_profile.h" - "internal/conformance_testing.h" - "internal/conformance_testing_helpers.h" - "internal/parentheses.h" - "internal/transform_args.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::algorithm - absl::debugging - absl::type_traits - absl::strings - absl::utility - GTest::gmock_main - TESTONLY -) - -absl_cc_test( - NAME - conformance_testing_test - SRCS - "internal/conformance_testing_test.cc" - COPTS - ${ABSL_TEST_COPTS} - ${ABSL_EXCEPTIONS_FLAG} - LINKOPTS - ${ABSL_EXCEPTIONS_FLAG_LINKOPTS} - DEPS - absl::conformance_testing - absl::type_traits - GTest::gmock_main -) - -absl_cc_test( - NAME - conformance_testing_test_no_exceptions - SRCS - "internal/conformance_testing_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::conformance_testing - absl::type_traits - GTest::gmock_main -) - absl_cc_library( NAME variant diff --git a/absl/types/internal/conformance_aliases.h b/absl/types/internal/conformance_aliases.h deleted file mode 100644 index 0cc6884e..00000000 --- a/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/absl/types/internal/conformance_archetype.h b/absl/types/internal/conformance_archetype.h deleted file mode 100644 index 2349e0f7..00000000 --- a/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/absl/types/internal/conformance_profile.h b/absl/types/internal/conformance_profile.h deleted file mode 100644 index 37b017db..00000000 --- a/absl/types/internal/conformance_profile.h +++ /dev/null @@ -1,933 +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) - -#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL -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); -#endif - -#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/absl/types/internal/conformance_testing.h b/absl/types/internal/conformance_testing.h deleted file mode 100644 index 487b0f78..00000000 --- a/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/absl/types/internal/conformance_testing_helpers.h b/absl/types/internal/conformance_testing_helpers.h deleted file mode 100644 index 00775f96..00000000 --- a/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/absl/types/internal/conformance_testing_test.cc b/absl/types/internal/conformance_testing_test.cc deleted file mode 100644 index cf262fa6..00000000 --- a/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/absl/types/internal/parentheses.h b/absl/types/internal/parentheses.h deleted file mode 100644 index 5aebee8f..00000000 --- a/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/absl/types/internal/transform_args.h b/absl/types/internal/transform_args.h deleted file mode 100644 index 4a0ab42a..00000000 --- a/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_ |