aboutsummaryrefslogtreecommitdiffhomepage
path: root/absl/types/internal/conformance_profile.h
diff options
context:
space:
mode:
Diffstat (limited to 'absl/types/internal/conformance_profile.h')
-rw-r--r--absl/types/internal/conformance_profile.h374
1 files changed, 374 insertions, 0 deletions
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 <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_