#ifndef ENTT_CORE_TYPE_TRAITS_HPP #define ENTT_CORE_TYPE_TRAITS_HPP #include #include #include #include #include "../config/config.h" #include "fwd.hpp" namespace entt { /** * @brief Utility class to disambiguate overloaded functions. * @tparam N Number of choices available. */ template struct choice_t // Unfortunately, doxygen cannot parse such a construct. : /*! @cond TURN_OFF_DOXYGEN */ choice_t /*! @endcond */ {}; /*! @copybrief choice_t */ template<> struct choice_t<0> {}; /** * @brief Variable template for the choice trick. * @tparam N Number of choices available. */ template inline constexpr choice_t choice{}; /** * @brief Identity type trait. * * Useful to establish non-deduced contexts in template argument deduction * (waiting for C++20) or to provide types through function arguments. * * @tparam Type A type. */ template struct type_identity { /*! @brief Identity type. */ using type = Type; }; /** * @brief Helper type. * @tparam Type A type. */ template using type_identity_t = typename type_identity::type; /** * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains. * @tparam Type The type of which to return the size. * @tparam The size of the type if `sizeof` accepts it, 0 otherwise. */ template struct size_of: std::integral_constant {}; /*! @copydoc size_of */ template struct size_of> : std::integral_constant {}; /** * @brief Helper variable template. * @tparam Type The type of which to return the size. */ template inline constexpr std::size_t size_of_v = size_of::value; /** * @brief Using declaration to be used to _repeat_ the same type a number of * times equal to the size of a given parameter pack. * @tparam Type A type to repeat. */ template using unpack_as_type = Type; /** * @brief Helper variable template to be used to _repeat_ the same value a * number of times equal to the size of a given parameter pack. * @tparam Value A value to repeat. */ template inline constexpr auto unpack_as_value = Value; /** * @brief Wraps a static constant. * @tparam Value A static constant. */ template using integral_constant = std::integral_constant; /** * @brief Alias template to facilitate the creation of named values. * @tparam Value A constant value at least convertible to `id_type`. */ template using tag = integral_constant; /** * @brief A class to use to push around lists of types, nothing more. * @tparam Type Types provided by the type list. */ template struct type_list { /*! @brief Type list type. */ using type = type_list; /*! @brief Compile-time number of elements in the type list. */ static constexpr auto size = sizeof...(Type); }; /*! @brief Primary template isn't defined on purpose. */ template struct type_list_element; /** * @brief Provides compile-time indexed access to the types of a type list. * @tparam Index Index of the type to return. * @tparam Type First type provided by the type list. * @tparam Other Other types provided by the type list. */ template struct type_list_element> : type_list_element> {}; /** * @brief Provides compile-time indexed access to the types of a type list. * @tparam Type First type provided by the type list. * @tparam Other Other types provided by the type list. */ template struct type_list_element<0u, type_list> { /*! @brief Searched type. */ using type = Type; }; /** * @brief Helper type. * @tparam Index Index of the type to return. * @tparam List Type list to search into. */ template using type_list_element_t = typename type_list_element::type; /** * @brief Concatenates multiple type lists. * @tparam Type Types provided by the first type list. * @tparam Other Types provided by the second type list. * @return A type list composed by the types of both the type lists. */ template constexpr type_list operator+(type_list, type_list) { return {}; } /*! @brief Primary template isn't defined on purpose. */ template struct type_list_cat; /*! @brief Concatenates multiple type lists. */ template<> struct type_list_cat<> { /*! @brief A type list composed by the types of all the type lists. */ using type = type_list<>; }; /** * @brief Concatenates multiple type lists. * @tparam Type Types provided by the first type list. * @tparam Other Types provided by the second type list. * @tparam List Other type lists, if any. */ template struct type_list_cat, type_list, List...> { /*! @brief A type list composed by the types of all the type lists. */ using type = typename type_list_cat, List...>::type; }; /** * @brief Concatenates multiple type lists. * @tparam Type Types provided by the type list. */ template struct type_list_cat> { /*! @brief A type list composed by the types of all the type lists. */ using type = type_list; }; /** * @brief Helper type. * @tparam List Type lists to concatenate. */ template using type_list_cat_t = typename type_list_cat::type; /*! @brief Primary template isn't defined on purpose. */ template struct type_list_unique; /** * @brief Removes duplicates types from a type list. * @tparam Type One of the types provided by the given type list. * @tparam Other The other types provided by the given type list. */ template struct type_list_unique> { /*! @brief A type list without duplicate types. */ using type = std::conditional_t< (std::is_same_v || ...), typename type_list_unique>::type, type_list_cat_t, typename type_list_unique>::type>>; }; /*! @brief Removes duplicates types from a type list. */ template<> struct type_list_unique> { /*! @brief A type list without duplicate types. */ using type = type_list<>; }; /** * @brief Helper type. * @tparam Type A type list. */ template using type_list_unique_t = typename type_list_unique::type; /** * @brief Provides the member constant `value` to true if a type list contains a * given type, false otherwise. * @tparam List Type list. * @tparam Type Type to look for. */ template struct type_list_contains; /** * @copybrief type_list_contains * @tparam Type Types provided by the type list. * @tparam Other Type to look for. */ template struct type_list_contains, Other>: std::disjunction...> {}; /** * @brief Helper variable template. * @tparam List Type list. * @tparam Type Type to look for. */ template inline constexpr bool type_list_contains_v = type_list_contains::value; /*! @brief Primary template isn't defined on purpose. */ template struct type_list_diff; /** * @brief Computes the difference between two type lists. * @tparam Type Types provided by the first type list. * @tparam Other Types provided by the second type list. */ template struct type_list_diff, type_list> { /*! @brief A type list that is the difference between the two type lists. */ using type = type_list_cat_t, Type>, type_list<>, type_list>...>; }; /** * @brief Helper type. * @tparam List Type lists between which to compute the difference. */ template using type_list_diff_t = typename type_list_diff::type; /** * @brief A class to use to push around lists of constant values, nothing more. * @tparam Value Values provided by the value list. */ template struct value_list { /*! @brief Value list type. */ using type = value_list; /*! @brief Compile-time number of elements in the value list. */ static constexpr auto size = sizeof...(Value); }; /*! @brief Primary template isn't defined on purpose. */ template struct value_list_element; /** * @brief Provides compile-time indexed access to the values of a value list. * @tparam Index Index of the value to return. * @tparam Value First value provided by the value list. * @tparam Other Other values provided by the value list. */ template struct value_list_element> : value_list_element> {}; /** * @brief Provides compile-time indexed access to the types of a type list. * @tparam Value First value provided by the value list. * @tparam Other Other values provided by the value list. */ template struct value_list_element<0u, value_list> { /*! @brief Searched value. */ static constexpr auto value = Value; }; /** * @brief Helper type. * @tparam Index Index of the value to return. * @tparam List Value list to search into. */ template inline constexpr auto value_list_element_v = value_list_element::value; /** * @brief Concatenates multiple value lists. * @tparam Value Values provided by the first value list. * @tparam Other Values provided by the second value list. * @return A value list composed by the values of both the value lists. */ template constexpr value_list operator+(value_list, value_list) { return {}; } /*! @brief Primary template isn't defined on purpose. */ template struct value_list_cat; /*! @brief Concatenates multiple value lists. */ template<> struct value_list_cat<> { /*! @brief A value list composed by the values of all the value lists. */ using type = value_list<>; }; /** * @brief Concatenates multiple value lists. * @tparam Value Values provided by the first value list. * @tparam Other Values provided by the second value list. * @tparam List Other value lists, if any. */ template struct value_list_cat, value_list, List...> { /*! @brief A value list composed by the values of all the value lists. */ using type = typename value_list_cat, List...>::type; }; /** * @brief Concatenates multiple value lists. * @tparam Value Values provided by the value list. */ template struct value_list_cat> { /*! @brief A value list composed by the values of all the value lists. */ using type = value_list; }; /** * @brief Helper type. * @tparam List Value lists to concatenate. */ template using value_list_cat_t = typename value_list_cat::type; /*! @brief Same as std::is_invocable, but with tuples. */ template struct is_applicable: std::false_type {}; /** * @copybrief is_applicable * @tparam Func A valid function type. * @tparam Tuple Tuple-like type. * @tparam Args The list of arguments to use to probe the function type. */ template class Tuple, typename... Args> struct is_applicable>: std::is_invocable {}; /** * @copybrief is_applicable * @tparam Func A valid function type. * @tparam Tuple Tuple-like type. * @tparam Args The list of arguments to use to probe the function type. */ template class Tuple, typename... Args> struct is_applicable>: std::is_invocable {}; /** * @brief Helper variable template. * @tparam Func A valid function type. * @tparam Args The list of arguments to use to probe the function type. */ template inline constexpr bool is_applicable_v = is_applicable::value; /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */ template struct is_applicable_r: std::false_type {}; /** * @copybrief is_applicable_r * @tparam Ret The type to which the return type of the function should be * convertible. * @tparam Func A valid function type. * @tparam Args The list of arguments to use to probe the function type. */ template struct is_applicable_r>: std::is_invocable_r {}; /** * @brief Helper variable template. * @tparam Ret The type to which the return type of the function should be * convertible. * @tparam Func A valid function type. * @tparam Args The list of arguments to use to probe the function type. */ template inline constexpr bool is_applicable_r_v = is_applicable_r::value; /** * @brief Provides the member constant `value` to true if a given type is * complete, false otherwise. * @tparam Type The type to test. */ template struct is_complete: std::false_type {}; /*! @copydoc is_complete */ template struct is_complete>: std::true_type {}; /** * @brief Helper variable template. * @tparam Type The type to test. */ template inline constexpr bool is_complete_v = is_complete::value; /** * @brief Provides the member constant `value` to true if a given type is an * iterator, false otherwise. * @tparam Type The type to test. */ template struct is_iterator: std::false_type {}; /** * @cond TURN_OFF_DOXYGEN * Internal details not to be documented. */ namespace internal { template struct has_iterator_category: std::false_type {}; template struct has_iterator_category::iterator_category>>: std::true_type {}; } // namespace internal /** * Internal details not to be documented. * @endcond */ /*! @copydoc is_iterator */ template struct is_iterator>, void>>> : internal::has_iterator_category {}; /** * @brief Helper variable template. * @tparam Type The type to test. */ template inline constexpr bool is_iterator_v = is_iterator::value; /** * @brief Provides the member constant `value` to true if a given type is both * an empty and non-final class, false otherwise. * @tparam Type The type to test */ template struct is_ebco_eligible : std::conjunction, std::negation>> {}; /** * @brief Helper variable template. * @tparam Type The type to test. */ template inline constexpr bool is_ebco_eligible_v = is_ebco_eligible::value; /** * @brief Provides the member constant `value` to true if `Type::is_transparent` * is valid and denotes a type, false otherwise. * @tparam Type The type to test. */ template struct is_transparent: std::false_type {}; /*! @copydoc is_transparent */ template struct is_transparent>: std::true_type {}; /** * @brief Helper variable template. * @tparam Type The type to test. */ template inline constexpr bool is_transparent_v = is_transparent::value; /** * @brief Provides the member constant `value` to true if a given type is * equality comparable, false otherwise. * @tparam Type The type to test. */ template struct is_equality_comparable: std::false_type {}; /** * @cond TURN_OFF_DOXYGEN * Internal details not to be documented. */ namespace internal { template struct has_tuple_size_value: std::false_type {}; template struct has_tuple_size_value::value)>>: std::true_type {}; template [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence) { return (is_equality_comparable>::value && ...); } template [[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) { return true; } template [[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval(), bool{}) { if constexpr(is_iterator_v) { return true; } else if constexpr(std::is_same_v) { return maybe_equality_comparable(choice<0>); } else { return is_equality_comparable::value; } } template [[nodiscard]] constexpr std::enable_if_t>>, bool> maybe_equality_comparable(choice_t<2>) { if constexpr(has_tuple_size_value::value) { return unpack_maybe_equality_comparable(std::make_index_sequence::value>{}); } else { return maybe_equality_comparable(choice<1>); } } } // namespace internal /** * Internal details not to be documented. * @endcond */ /*! @copydoc is_equality_comparable */ template struct is_equality_comparable() == std::declval())>> : std::bool_constant(choice<2>)> {}; /** * @brief Helper variable template. * @tparam Type The type to test. */ template inline constexpr bool is_equality_comparable_v = is_equality_comparable::value; /** * @brief Transcribes the constness of a type to another type. * @tparam To The type to which to transcribe the constness. * @tparam From The type from which to transcribe the constness. */ template struct constness_as { /*! @brief The type resulting from the transcription of the constness. */ using type = std::remove_const_t; }; /*! @copydoc constness_as */ template struct constness_as { /*! @brief The type resulting from the transcription of the constness. */ using type = std::add_const_t; }; /** * @brief Alias template to facilitate the transcription of the constness. * @tparam To The type to which to transcribe the constness. * @tparam From The type from which to transcribe the constness. */ template using constness_as_t = typename constness_as::type; /** * @brief Extracts the class of a non-static member object or function. * @tparam Member A pointer to a non-static member object or function. */ template class member_class { static_assert(std::is_member_pointer_v, "Invalid pointer type to non-static member object or function"); template static Class *clazz(Ret (Class::*)(Args...)); template static Class *clazz(Ret (Class::*)(Args...) const); template static Class *clazz(Type Class::*); public: /*! @brief The class of the given non-static member object or function. */ using type = std::remove_pointer_t()))>; }; /** * @brief Helper type. * @tparam Member A pointer to a non-static member object or function. */ template using member_class_t = typename member_class::type; } // namespace entt #endif