From c6e9534b52627882ba8d4fff40c02edab95697dd Mon Sep 17 00:00:00 2001 From: BlackMark Date: Tue, 7 Apr 2020 19:13:34 +0200 Subject: [PATCH] Reimplement and extend using implementation suggestions from cppref --- type.hpp | 184 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 133 insertions(+), 51 deletions(-) diff --git a/type.hpp b/type.hpp index cff5df6..6397016 100644 --- a/type.hpp +++ b/type.hpp @@ -7,141 +7,223 @@ #include #include +#include namespace type { +// + // clang-format off -template struct set_bool { static constexpr auto value = Val; }; +template struct remove_reference { using type = T; }; +template struct remove_reference { using type = T; }; +template struct remove_reference { using type = T; }; +template using remove_reference_t = typename remove_reference::type; -struct true_type : set_bool {}; -struct false_type : set_bool {}; +namespace detail { -template struct always_false : false_type {}; + template struct type_identity { using type = T; }; -template static constexpr auto always_false_v = always_false::value; + template auto try_add_pointer(int) -> type_identity *>; + template auto try_add_pointer(...) -> type_identity; -template struct is_integral : false_type {}; -template <> struct is_integral : true_type {}; -template <> struct is_integral : true_type {}; -template <> struct is_integral : true_type {}; -template <> struct is_integral : true_type {}; -template <> struct is_integral : true_type {}; -template <> struct is_integral : true_type {}; -template <> struct is_integral : true_type {}; -template <> struct is_integral : true_type {}; -template <> struct is_integral : true_type {}; -template <> struct is_integral : true_type {}; -template <> struct is_integral : true_type {}; -template <> struct is_integral : true_type {}; +} // namespace detail -template static constexpr auto is_integral_v = is_integral::value; +template +struct integral_constant { + static constexpr T value = v; + using value_type = T; + using type = integral_constant; // using injected-class-name + constexpr operator value_type() const noexcept { return value; } + constexpr value_type operator()() const noexcept { return value; } // since c++14 +}; +template using bool_constant = integral_constant; +using false_type = bool_constant; +using true_type = bool_constant; -template struct is_floating_point : false_type {}; -template <> struct is_floating_point : true_type {}; -template <> struct is_floating_point : true_type {}; -template <> struct is_floating_point : true_type {}; +template struct conditional { using type = T; }; +template struct conditional { using type = F; }; +template using conditional_t = typename conditional::type; -template static constexpr auto is_floating_point_v = is_floating_point::value; +template struct is_array : false_type {}; +template struct is_array : true_type {}; +template struct is_array : true_type {}; +template inline constexpr bool is_array_v = is_array::value; + +template struct remove_extent { using type = T; }; +template struct remove_extent { using type = T; }; +template struct remove_extent { using type = T; }; +template using remove_extent_t = typename remove_extent::type; + +template struct is_const : false_type {}; +template struct is_const : true_type {}; +template inline constexpr bool is_const_v = is_const::value; + +template struct is_reference : false_type {}; +template struct is_reference : true_type {}; +template struct is_reference : true_type {}; +template inline constexpr bool is_reference_v = is_reference::value; + +template struct is_function : integral_constant && !is_reference_v> {}; +template inline constexpr bool is_function_v = is_function::value; + +template struct add_pointer : decltype(detail::try_add_pointer(0)) {}; +template using add_pointer_t = typename add_pointer::type; + +template struct remove_cv { using type = T; }; +template struct remove_cv { using type = T; }; +template struct remove_cv { using type = T; }; +template struct remove_cv { using type = T; }; +template struct remove_const { using type = T; }; +template struct remove_const { using type = T; }; +template struct remove_volatile { using type = T; }; +template struct remove_volatile { using type = T; }; +template using remove_cv_t = typename remove_cv::type; +template using remove_const_t = typename remove_const::type; +template using remove_volatile_t = typename remove_volatile::type; + +template +struct decay { +private: + using U = remove_reference_t; +public: + using type = conditional_t, + remove_extent_t *, + conditional_t::value, + add_pointer_t, + remove_cv_t + > + >; +}; +template using decay_t = typename decay::type; template struct is_same : false_type {}; template struct is_same : true_type {}; - -template static constexpr auto is_same_v = is_same::value; +template inline constexpr auto is_same_v = is_same::value; template -struct NumericLimits { - static constexpr T min() { return T(); } - static constexpr T max() { return T(); } -}; +struct is_floating_point : integral_constant> || + is_same_v> || + is_same_v>> +{}; +template inline constexpr auto is_floating_point_v = is_floating_point::value; + +template +struct is_integral : integral_constant> || + is_same_v> || + is_same_v> || + is_same_v> || + is_same_v> || + is_same_v> || + is_same_v> || + is_same_v> || + is_same_v> || + is_same_v> || + is_same_v> || + is_same_v> || + is_same_v> || + is_same_v> || + is_same_v>> +{}; +template inline constexpr auto is_integral_v = is_integral::value; + +// Not part of , but very useful +template struct always_false : false_type {}; +template inline constexpr auto always_false_v = always_false::value; + +// + +template struct numeric_limits {}; template <> -struct NumericLimits { +struct numeric_limits { static constexpr bool min() { return false; } static constexpr bool max() { return true; } }; template <> -struct NumericLimits { +struct numeric_limits { static constexpr char min() { return CHAR_MIN; } static constexpr char max() { return CHAR_MAX; } }; template <> -struct NumericLimits { +struct numeric_limits { static constexpr signed char min() { return SCHAR_MIN; } static constexpr signed char max() { return SCHAR_MAX; } }; template <> -struct NumericLimits { +struct numeric_limits { static constexpr unsigned char min() { return 0; } static constexpr unsigned char max() { return UCHAR_MAX; } }; template <> -struct NumericLimits { +struct numeric_limits { static constexpr short min() { return SHRT_MIN; } static constexpr short max() { return SHRT_MAX; } }; template <> -struct NumericLimits { +struct numeric_limits { static constexpr int min() { return INT_MIN; } static constexpr int max() { return INT_MAX; } }; template <> -struct NumericLimits { +struct numeric_limits { static constexpr long int min() { return LONG_MIN; } static constexpr long int max() { return LONG_MAX; } }; template <> -struct NumericLimits { +struct numeric_limits { static constexpr long long int min() { return LLONG_MIN; } static constexpr long long int max() { return LLONG_MAX; } }; template <> -struct NumericLimits { +struct numeric_limits { static constexpr unsigned short min() { return 0; } static constexpr unsigned short max() { return USHRT_MAX; } }; template <> -struct NumericLimits { +struct numeric_limits { static constexpr unsigned int min() { return 0; } static constexpr unsigned int max() { return UINT_MAX; } }; template <> -struct NumericLimits { +struct numeric_limits { static constexpr unsigned long int min() { return 0; } static constexpr unsigned long int max() { return ULONG_MAX; } }; template <> -struct NumericLimits { +struct numeric_limits { static constexpr unsigned long long int min() { return 0; } static constexpr unsigned long long int max() { return ULLONG_MAX; } }; template <> -struct NumericLimits { - template static constexpr float min() { return FLT_MIN; } - template static constexpr float max() { return FLT_MAX; } +struct numeric_limits { + static constexpr float min() { return FLT_MIN; } + static constexpr float max() { return FLT_MAX; } }; template <> -struct NumericLimits { - template static constexpr double min() { return DBL_MIN; } - template static constexpr double max() { return DBL_MAX; } +struct numeric_limits { + static constexpr double min() { return DBL_MIN; } + static constexpr double max() { return DBL_MAX; } }; template <> -struct NumericLimits { - template static constexpr long double min() { return LDBL_MIN; } - template static constexpr long double max() { return LDBL_MAX; } +struct numeric_limits { + static constexpr long double min() { return LDBL_MIN; } + static constexpr long double max() { return LDBL_MAX; } }; // clang-format on