Commit d659fe54 by Abseil Team Committed by Mark Barolak

Export of internal Abseil changes

--
c385118b3ef0528d150bfe7aeeb63e77f9e463cd by Matt Calabrese <calabrese@google.com>:

Internal-only Archetype generation for testing generic code with user-defined types of various properties.

PiperOrigin-RevId: 283833099

--
4ccf340d3b295aa5b796ee5c97128b61d38899ea by Derek Mauro <dmauro@google.com>:

Fixes the flags parse_test.
Windows doesn't like consecutive path separators.

PiperOrigin-RevId: 283614649

--
5df6d83acb1e49cd1da785cfaf7551f05149f3c9 by Andy Getzendanner <durandal@google.com>:

ABSL_INTERNAL_LOG: forward complete __FILE__ to internal_log_function; not just basename.

PiperOrigin-RevId: 283406080
GitOrigin-RevId: c385118b3ef0528d150bfe7aeeb63e77f9e463cd
Change-Id: Ib0782354691a73fc40185c3262cfd507085b3393
parent a4b757b5
......@@ -70,14 +70,10 @@
//
// The API is a subset of the above: each macro only takes two arguments. Use
// StrCat if you need to build a richer message.
#define ABSL_INTERNAL_LOG(severity, message) \
do { \
constexpr const char* absl_raw_logging_internal_basename = \
::absl::raw_logging_internal::Basename(__FILE__, \
sizeof(__FILE__) - 1); \
::absl::raw_logging_internal::internal_log_function( \
ABSL_RAW_LOGGING_INTERNAL_##severity, \
absl_raw_logging_internal_basename, __LINE__, message); \
#define ABSL_INTERNAL_LOG(severity, message) \
do { \
::absl::raw_logging_internal::internal_log_function( \
ABSL_RAW_LOGGING_INTERNAL_##severity, __FILE__, __LINE__, message); \
} while (0)
#define ABSL_INTERNAL_CHECK(condition, message) \
......
......@@ -22,6 +22,7 @@
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/scoped_set_env.h"
#include "absl/flags/flag.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/substitute.h"
#include "absl/types/span.h"
......@@ -92,8 +93,11 @@ const std::string& GetTestTempDir() {
auto len = GetTempPathA(MAX_PATH, temp_path_buffer);
if (len < MAX_PATH && len != 0) {
std::string temp_dir_name = absl::StrCat(
temp_path_buffer, "\\parse_test.", GetCurrentProcessId());
std::string temp_dir_name = temp_path_buffer;
if (!absl::EndsWith(temp_dir_name, "\\")) {
temp_dir_name.push_back('\\');
}
absl::StrAppend(&temp_dir_name, "parse_test.", GetCurrentProcessId());
if (CreateDirectoryA(temp_dir_name.c_str(), nullptr)) {
*res = temp_dir_name;
}
......@@ -104,11 +108,11 @@ const std::string& GetTestTempDir() {
*res = unique_name;
}
#endif
}
if (res->empty()) {
ABSL_INTERNAL_LOG(FATAL,
"Failed to make temporary directory for data files");
}
if (res->empty()) {
ABSL_INTERNAL_LOG(FATAL,
"Failed to make temporary directory for data files");
}
#ifdef _WIN32
......
......@@ -41,10 +41,20 @@
#include "absl/base/config.h"
// MSVC constructibility traits do not detect destructor properties and so our
// implementations should not use them as a source-of-truth.
#if defined(_MSC_VER) && !defined(__clang__) && !defined(__GNUC__)
#define ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION 1
#endif
namespace absl {
// Defined and documented later on in this file.
template <typename T>
struct is_trivially_destructible;
// Defined and documented later on in this file.
template <typename T>
struct is_trivially_move_assignable;
namespace type_traits_internal {
......@@ -66,6 +76,20 @@ union SingleMemberUnion {
#endif // defined(_MSC_VER) && !defined(__GNUC__)
template <class T>
struct IsTriviallyMoveConstructibleObject
: std::integral_constant<
bool, std::is_move_constructible<
type_traits_internal::SingleMemberUnion<T>>::value &&
absl::is_trivially_destructible<T>::value> {};
template <class T>
struct IsTriviallyCopyConstructibleObject
: std::integral_constant<
bool, std::is_copy_constructible<
type_traits_internal::SingleMemberUnion<T>>::value &&
absl::is_trivially_destructible<T>::value> {};
template <class T>
struct IsTriviallyMoveAssignableReference : std::false_type {};
template <class T>
......@@ -323,7 +347,9 @@ struct is_trivially_default_constructible
: std::integral_constant<bool, __has_trivial_constructor(T) &&
std::is_default_constructible<T>::value &&
is_trivially_destructible<T>::value> {
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \
!defined( \
ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION)
private:
static constexpr bool compliant =
std::is_trivially_default_constructible<T>::value ==
......@@ -354,10 +380,11 @@ template <typename T>
struct is_trivially_move_constructible
: std::conditional<
std::is_object<T>::value && !std::is_array<T>::value,
std::is_move_constructible<
type_traits_internal::SingleMemberUnion<T>>,
type_traits_internal::IsTriviallyMoveConstructibleObject<T>,
std::is_reference<T>>::type::type {
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \
!defined( \
ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION)
private:
static constexpr bool compliant =
std::is_trivially_move_constructible<T>::value ==
......@@ -388,10 +415,11 @@ template <typename T>
struct is_trivially_copy_constructible
: std::conditional<
std::is_object<T>::value && !std::is_array<T>::value,
std::is_copy_constructible<
type_traits_internal::SingleMemberUnion<T>>,
type_traits_internal::IsTriviallyCopyConstructibleObject<T>,
std::is_lvalue_reference<T>>::type::type {
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \
!defined( \
ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION)
private:
static constexpr bool compliant =
std::is_trivially_copy_constructible<T>::value ==
......@@ -423,7 +451,8 @@ struct is_trivially_copy_constructible
template <typename T>
struct is_trivially_move_assignable
: std::conditional<
std::is_object<T>::value && !std::is_array<T>::value,
std::is_object<T>::value && !std::is_array<T>::value &&
std::is_move_assignable<T>::value,
std::is_move_assignable<type_traits_internal::SingleMemberUnion<T>>,
type_traits_internal::IsTriviallyMoveAssignableReference<T>>::type::
type {
......
......@@ -347,21 +347,6 @@ class Base {
virtual ~Base() {}
};
// In GCC/Clang, std::is_trivially_constructible requires that the destructor is
// trivial. However, MSVC doesn't require that. This results in different
// behavior when checking is_trivially_constructible on any type with
// nontrivial destructor. Since absl::is_trivially_default_constructible and
// absl::is_trivially_copy_constructible both follows Clang/GCC's interpretation
// and check is_trivially_destructible, it results in inconsistency with
// std::is_trivially_xxx_constructible on MSVC. This macro is used to work
// around this issue in test. In practice, a trivially constructible type
// should also be trivially destructible.
// GCC bug 51452: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51452
// LWG issue 2116: http://cplusplus.github.io/LWG/lwg-active.html#2116
#ifndef _MSC_VER
#define ABSL_TRIVIALLY_CONSTRUCTIBLE_VERIFY_TRIVIALLY_DESTRUCTIBLE 1
#endif
// Old versions of libc++, around Clang 3.5 to 3.6, consider deleted destructors
// as also being trivial. With the resolution of CWG 1928 and CWG 1734, this
// is no longer considered true and has thus been amended.
......@@ -499,11 +484,9 @@ TEST(TypeTraitsTest, TestTrivialDefaultCtor) {
EXPECT_FALSE(
absl::is_trivially_default_constructible<DeletedDefaultCtor>::value);
#ifdef ABSL_TRIVIALLY_CONSTRUCTIBLE_VERIFY_TRIVIALLY_DESTRUCTIBLE
// types with nontrivial destructor are nontrivial
EXPECT_FALSE(
absl::is_trivially_default_constructible<NontrivialDestructor>::value);
#endif
// types with vtables
EXPECT_FALSE(absl::is_trivially_default_constructible<Base>::value);
......@@ -607,11 +590,9 @@ TEST(TypeTraitsTest, TestTrivialMoveCtor) {
EXPECT_FALSE(
absl::is_trivially_move_constructible<NonCopyableOrMovable>::value);
#ifdef ABSL_TRIVIALLY_CONSTRUCTIBLE_VERIFY_TRIVIALLY_DESTRUCTIBLE
// type with nontrivial destructor are nontrivial move construbtible
EXPECT_FALSE(
absl::is_trivially_move_constructible<NontrivialDestructor>::value);
#endif
// types with vtables
EXPECT_FALSE(absl::is_trivially_move_constructible<Base>::value);
......@@ -682,11 +663,9 @@ TEST(TypeTraitsTest, TestTrivialCopyCtor) {
EXPECT_FALSE(
absl::is_trivially_copy_constructible<NonCopyableOrMovable>::value);
#ifdef ABSL_TRIVIALLY_CONSTRUCTIBLE_VERIFY_TRIVIALLY_DESTRUCTIBLE
// type with nontrivial destructor are nontrivial copy construbtible
EXPECT_FALSE(
absl::is_trivially_copy_constructible<NontrivialDestructor>::value);
#endif
// types with vtables
EXPECT_FALSE(absl::is_trivially_copy_constructible<Base>::value);
......
......@@ -209,6 +209,40 @@ cc_test(
)
cc_library(
name = "conformance_testing",
testonly = 1,
hdrs = [
"internal/conformance_aliases.h",
"internal/conformance_archetype.h",
"internal/conformance_profile.h",
],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
"//absl/debugging:demangle_internal",
"//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"],
......
......@@ -240,6 +240,52 @@ absl_cc_test(
absl_cc_library(
NAME
conformance_testing
HDRS
"internal/conformance_aliases.h"
"internal/conformance_archetype.h"
"internal/conformance_profile.h"
COPTS
${ABSL_DEFAULT_COPTS}
DEPS
absl::debugging
absl::type_traits
absl::strings
absl::utility
gmock_main
PUBLIC
)
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
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
gmock_main
)
absl_cc_library(
NAME
variant
HDRS
"variant.h"
......
// 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 {
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
} // namespace absl
#undef ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS
#endif // ABSL_TYPES_INTERNAL_CONFORMANCE_ALIASES_H_
// 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 {
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
} // 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_
// 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 <type_traits>
#include <utility>
#include "absl/meta/type_traits.h"
// TODO(calabrese) Add support for extending profiles.
namespace absl {
namespace types_internal {
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.
enum class function_kind { maybe, yes, nothrow, trivial };
#define ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM(name) \
enum class name { maybe, yes, nothrow, trivial }
ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM(default_constructible);
ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM(move_constructible);
ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM(copy_constructible);
ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM(move_assignable);
ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM(copy_assignable);
ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM(destructible);
#undef ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM
#define ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM(name) \
enum class name { maybe, yes, nothrow }
ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM(equality_comparable);
ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM(inequality_comparable);
ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM(less_than_comparable);
ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM(less_equal_comparable);
ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM(greater_equal_comparable);
ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM(greater_than_comparable);
ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM(swappable);
#undef ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM
enum class hashable { maybe, yes };
constexpr const char* PropertyName(hashable v) {
return "support for std::hash";
}
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;
};
#define ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL(type, name) \
template <default_constructible DefaultConstructibleValue, \
move_constructible MoveConstructibleValue, \
copy_constructible CopyConstructibleValue, \
move_assignable MoveAssignableValue, \
copy_assignable CopyAssignableValue, \
destructible DestructibleValue, \
equality_comparable EqualityComparableValue, \
inequality_comparable InequalityComparableValue, \
less_than_comparable LessThanComparableValue, \
less_equal_comparable LessEqualComparableValue, \
greater_equal_comparable GreaterEqualComparableValue, \
greater_than_comparable GreaterThanComparableValue, \
swappable SwappableValue, hashable HashableValue> \
constexpr type ConformanceProfile< \
DefaultConstructibleValue, MoveConstructibleValue, \
CopyConstructibleValue, MoveAssignableValue, CopyAssignableValue, \
DestructibleValue, EqualityComparableValue, InequalityComparableValue, \
LessThanComparableValue, LessEqualComparableValue, \
GreaterEqualComparableValue, GreaterThanComparableValue, SwappableValue, \
HashableValue>::name
#define ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(type) \
ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL(type, \
type##_support); \
ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL(bool, is_##type)
ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(default_constructible);
ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(move_constructible);
ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(copy_constructible);
ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(move_assignable);
ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(copy_assignable);
ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(destructible);
ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(equality_comparable);
ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(inequality_comparable);
ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(less_than_comparable);
ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(less_equal_comparable);
ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(greater_equal_comparable);
ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(greater_than_comparable);
ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(swappable);
ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(hashable);
#undef ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF
#undef ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL
// Converts an enum to its underlying integral value.
template <class Enum>
constexpr absl::underlying_type_t<Enum> UnderlyingValue(Enum value) {
return static_cast<absl::underlying_type_t<Enum>>(value);
}
// 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 {};
} // namespace types_internal
} // namespace absl
#endif // ABSL_TYPES_INTERNAL_CONFORMANCE_PROFILE_H_
// 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 <new>
#include <type_traits>
#include <utility>
#include "gtest/gtest.h"
#include "absl/meta/type_traits.h"
#include "absl/types/internal/conformance_aliases.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);
// TODO(calabrese) Test runtime results
} // namespace
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment