diff --git a/include/stdx/type_traits.hpp b/include/stdx/type_traits.hpp index 11d2ce0..350296d 100644 --- a/include/stdx/type_traits.hpp +++ b/include/stdx/type_traits.hpp @@ -228,12 +228,43 @@ template constexpr auto is_cx_value_v> = true; #if __cplusplus >= 202002L +namespace detail { +template struct shrinkwrap { + using is_shrinkwrapped = void; + using type = T; +}; + template -using shrink_t = decltype([]() -> T (*)() { return nullptr; }); +concept is_shrinkwrapped = requires { typename T::is_shrinkwrapped; }; -template using expand_t = decltype(T{}()()); +template auto (*)() -> shrinkwrap { return nullptr; }> +CONSTEVAL auto shrink() { + return F; +} + +template +concept is_shrunk = requires(T t) { + { t()() } -> is_shrinkwrapped; +}; + +template CONSTEVAL auto maybe_expand() -> T; +template +CONSTEVAL auto maybe_expand() -> typename decltype(T{}()())::type; +} // namespace detail + +template CONSTEVAL auto shrink() -> decltype(detail::shrink()); + +template +CONSTEVAL auto expand() -> decltype(detail::maybe_expand()); +#else +template CONSTEVAL auto shrink() -> T; +template CONSTEVAL auto expand() -> T; #endif +template using shrink_t = decltype(shrink()); +template using expand_t = decltype(expand()); + STDX_PRAGMA(diagnostic push) #ifdef __clang__ STDX_PRAGMA(diagnostic ignored "-Wunknown-warning-option") diff --git a/include/stdx/utility.hpp b/include/stdx/utility.hpp index 0f6ff37..18ebd01 100644 --- a/include/stdx/utility.hpp +++ b/include/stdx/utility.hpp @@ -29,6 +29,8 @@ namespace detail { template struct value_t { constexpr static inline auto value = V; }; + +template struct type_map : Ts... {}; } // namespace detail template struct type_pair { @@ -43,7 +45,7 @@ template using tv_pair = tt_pair>; template using vv_pair = tt_pair, detail::value_t>; -template struct type_map : Ts... {}; +template using type_map = shrink_t>; namespace detail { template @@ -58,20 +60,19 @@ constexpr static auto reverse_lookup(type_pair) -> K; } // namespace detail template -using type_lookup_t = decltype(detail::lookup(std::declval())); +using type_lookup_t = decltype(detail::lookup(expand())); template using reverse_type_lookup_t = - decltype(detail::reverse_lookup(std::declval())); + decltype(detail::reverse_lookup(expand())); template using value_lookup_t = - decltype(detail::lookup, Default>(std::declval())); + decltype(detail::lookup, Default>(expand())); template using reverse_value_lookup_t = - decltype(detail::reverse_lookup, Default>( - std::declval())); + decltype(detail::reverse_lookup, Default>(expand())); namespace detail { template @@ -81,27 +82,26 @@ using is_not_void = std::bool_constant>; template constexpr static auto type_lookup_v = type_or_t(std::declval())), + decltype(detail::lookup(expand())), detail::value_t>::value; template constexpr static auto reverse_type_lookup_v = type_or_t(std::declval())), + decltype(detail::reverse_lookup(expand())), detail::value_t>::value; template constexpr static auto value_lookup_v = type_or_t, void>( - std::declval())), + decltype(detail::lookup, void>(expand())), detail::value_t>::value; template constexpr static auto reverse_value_lookup_v = type_or_t, void>( - std::declval())), + expand())), detail::value_t>::value; #if __cpp_lib_forward_like < 202207L diff --git a/test/type_traits.cpp b/test/type_traits.cpp index ff9b9ec..026210b 100644 --- a/test/type_traits.cpp +++ b/test/type_traits.cpp @@ -255,9 +255,9 @@ TEST_CASE("type shrinkage", "[type_traits]") { using B = long_type_name; using C = long_type_name; using X = stdx::shrink_t; - STATIC_REQUIRE(stdx::type_as_string().size() < - stdx::type_as_string().size()); - STATIC_REQUIRE(std::same_as, C>); + STATIC_CHECK(stdx::type_as_string().size() < + stdx::type_as_string().size()); + STATIC_CHECK(std::same_as, C>); } #endif