#pragma once // Fix for limits.h not exposing LLONG_MIN, LLONG_MIN, and ULLONG_MAX to C++ context #ifdef __cplusplus #define __STDC_VERSION__ 201112L #endif #include #include #include namespace type { // // clang-format off 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; namespace detail { template struct type_identity { using type = T; }; template auto try_add_pointer(int) -> type_identity *>; template auto try_add_pointer(...) -> type_identity; } // namespace detail 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 conditional { using type = T; }; template struct conditional { using type = F; }; template using conditional_t = typename conditional::type; 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 inline constexpr auto is_same_v = is_same::value; template 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 numeric_limits { static constexpr bool min() { return false; } static constexpr bool max() { return true; } }; template <> struct numeric_limits { static constexpr char min() { return CHAR_MIN; } static constexpr char max() { return CHAR_MAX; } }; template <> struct numeric_limits { static constexpr signed char min() { return SCHAR_MIN; } static constexpr signed char max() { return SCHAR_MAX; } }; template <> struct numeric_limits { static constexpr unsigned char min() { return 0; } static constexpr unsigned char max() { return UCHAR_MAX; } }; template <> struct numeric_limits { static constexpr short min() { return SHRT_MIN; } static constexpr short max() { return SHRT_MAX; } }; template <> struct numeric_limits { static constexpr int min() { return INT_MIN; } static constexpr int max() { return INT_MAX; } }; template <> struct numeric_limits { static constexpr long int min() { return LONG_MIN; } static constexpr long int max() { return LONG_MAX; } }; template <> struct numeric_limits { static constexpr long long int min() { return LLONG_MIN; } static constexpr long long int max() { return LLONG_MAX; } }; template <> struct numeric_limits { static constexpr unsigned short min() { return 0; } static constexpr unsigned short max() { return USHRT_MAX; } }; template <> struct numeric_limits { static constexpr unsigned int min() { return 0; } static constexpr unsigned int max() { return UINT_MAX; } }; template <> struct numeric_limits { static constexpr unsigned long int min() { return 0; } static constexpr unsigned long int max() { return ULONG_MAX; } }; template <> struct numeric_limits { static constexpr unsigned long long int min() { return 0; } static constexpr unsigned long long int max() { return ULLONG_MAX; } }; template <> struct numeric_limits { static constexpr float min() { return FLT_MIN; } static constexpr float max() { return FLT_MAX; } }; template <> struct numeric_limits { static constexpr double min() { return DBL_MIN; } static constexpr double max() { return DBL_MAX; } }; template <> struct numeric_limits { static constexpr long double min() { return LDBL_MIN; } static constexpr long double max() { return LDBL_MAX; } }; // clang-format on } // namespace type