From d659fe54b35ab9b8e35c72e50a4b8814167d5a84 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Wed, 4 Dec 2019 14:13:43 -0800 Subject: Export of internal Abseil changes -- c385118b3ef0528d150bfe7aeeb63e77f9e463cd by Matt Calabrese : Internal-only Archetype generation for testing generic code with user-defined types of various properties. PiperOrigin-RevId: 283833099 -- 4ccf340d3b295aa5b796ee5c97128b61d38899ea by Derek Mauro : Fixes the flags parse_test. Windows doesn't like consecutive path separators. PiperOrigin-RevId: 283614649 -- 5df6d83acb1e49cd1da785cfaf7551f05149f3c9 by Andy Getzendanner : ABSL_INTERNAL_LOG: forward complete __FILE__ to internal_log_function; not just basename. PiperOrigin-RevId: 283406080 GitOrigin-RevId: c385118b3ef0528d150bfe7aeeb63e77f9e463cd Change-Id: Ib0782354691a73fc40185c3262cfd507085b3393 --- absl/types/internal/conformance_profile.h | 374 ++++++++++++++++++++++++++++++ 1 file changed, 374 insertions(+) create mode 100644 absl/types/internal/conformance_profile.h (limited to 'absl/types/internal/conformance_profile.h') diff --git a/absl/types/internal/conformance_profile.h b/absl/types/internal/conformance_profile.h new file mode 100644 index 0000000..dce3bbe --- /dev/null +++ b/absl/types/internal/conformance_profile.h @@ -0,0 +1,374 @@ +// 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 +#include + +#include "absl/meta/type_traits.h" + +// TODO(calabrese) Add support for extending profiles. + +namespace absl { +namespace types_internal { + +template +struct PropertiesOfImpl {}; + +template +struct PropertiesOfImpl> { + using type = typename T::properties; +}; + +template +struct PropertiesOfImpl> { + using type = typename PropertiesOfImpl::type; +}; + +template +struct PropertiesOf : PropertiesOfImpl {}; + +template +using PropertiesOfT = typename PropertiesOf::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 \ + 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 +constexpr absl::underlying_type_t UnderlyingValue(Enum value) { + return static_cast>(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 +constexpr H MaxEnum(H head) { + return head; +} + +template +constexpr H MaxEnum(H head, N next, T... tail) { + return (UnderlyingValue)(next) < (UnderlyingValue)(head) + ? (MaxEnum)(head, tail...) + : (MaxEnum)(next, tail...); +} + +template +struct CombineProfilesImpl { + static constexpr default_constructible + default_constructible_support = // NOLINT + (MaxEnum)(PropertiesOfT::default_constructible_support...); + + static constexpr move_constructible move_constructible_support = // NOLINT + (MaxEnum)(PropertiesOfT::move_constructible_support...); + + static constexpr copy_constructible copy_constructible_support = // NOLINT + (MaxEnum)(PropertiesOfT::copy_constructible_support...); + + static constexpr move_assignable move_assignable_support = // NOLINT + (MaxEnum)(PropertiesOfT::move_assignable_support...); + + static constexpr copy_assignable copy_assignable_support = // NOLINT + (MaxEnum)(PropertiesOfT::copy_assignable_support...); + + static constexpr destructible destructible_support = // NOLINT + (MaxEnum)(PropertiesOfT::destructible_support...); + + static constexpr equality_comparable equality_comparable_support = // NOLINT + (MaxEnum)(PropertiesOfT::equality_comparable_support...); + + static constexpr inequality_comparable + inequality_comparable_support = // NOLINT + (MaxEnum)(PropertiesOfT::inequality_comparable_support...); + + static constexpr less_than_comparable + less_than_comparable_support = // NOLINT + (MaxEnum)(PropertiesOfT::less_than_comparable_support...); + + static constexpr less_equal_comparable + less_equal_comparable_support = // NOLINT + (MaxEnum)(PropertiesOfT::less_equal_comparable_support...); + + static constexpr greater_equal_comparable + greater_equal_comparable_support = // NOLINT + (MaxEnum)(PropertiesOfT::greater_equal_comparable_support...); + + static constexpr greater_than_comparable + greater_than_comparable_support = // NOLINT + (MaxEnum)(PropertiesOfT::greater_than_comparable_support...); + + static constexpr swappable swappable_support = // NOLINT + (MaxEnum)(PropertiesOfT::swappable_support...); + + static constexpr hashable hashable_support = // NOLINT + (MaxEnum)(PropertiesOfT::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 +struct CombineProfiles { + using profile_alias_of = CombineProfilesImpl; +}; + +template <> +struct CombineProfiles<> { + using properties = ConformanceProfile<>; +}; + +template +struct StrongProfileTypedef { + using properties = PropertiesOfT; +}; + +template +struct IsProfileImpl : std::false_type {}; + +template +struct IsProfileImpl>> : std::true_type {}; + +template +struct IsProfile : IsProfileImpl::type {}; + +} // namespace types_internal +} // namespace absl + +#endif // ABSL_TYPES_INTERNAL_CONFORMANCE_PROFILE_H_ -- cgit v1.2.3