From 461780490503a8bace011ca34e89288b35602fa3 Mon Sep 17 00:00:00 2001 From: Ben Deane Date: Thu, 6 Mar 2025 14:55:07 -0700 Subject: [PATCH] :art: Keep environment types as small as possible Problem: - When extending or appending environments it's easy for the type to balloon in size. Solution: - Strip duplicate queries from an environment. --- include/stdx/env.hpp | 14 +++++++++++--- test/env.cpp | 23 +++++++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/include/stdx/env.hpp b/include/stdx/env.hpp index a4c6a40..5da6d5e 100644 --- a/include/stdx/env.hpp +++ b/include/stdx/env.hpp @@ -12,7 +12,9 @@ namespace stdx { inline namespace v1 { namespace _env { template struct ct_prop { - [[nodiscard]] CONSTEVAL static auto query(decltype(Query)) noexcept { + using query_t = std::remove_cvref_t; + + [[nodiscard]] CONSTEVAL static auto query(query_t) noexcept { return Value; } }; @@ -61,6 +63,9 @@ template struct autowrap> { template autowrap(T) -> autowrap; template autowrap(str_lit_t) -> autowrap>; +template +using queries_equal = std::is_same; + template struct for_each_pair; template struct for_each_pair> { template @@ -72,7 +77,8 @@ template > constexpr auto make_env = [] { using new_env_t = typename for_each_pair< std::make_index_sequence>::template type; - return boost::mp11::mp_append{}; + return boost::mp11::mp_unique_if, + queries_equal>{}; }; } // namespace _env @@ -81,7 +87,9 @@ using extend_env_t = decltype(_env::make_env.template operator()()); template -using append_env_t = boost::mp11::mp_reverse>; +using append_env_t = boost::mp11::mp_unique_if< + boost::mp11::mp_reverse>, + _env::queries_equal>; template <_env::autowrap... Args> using make_env_t = extend_env_t, Args...>; diff --git a/test/env.cpp b/test/env.cpp index 2a72559..6449b0f 100644 --- a/test/env.cpp +++ b/test/env.cpp @@ -1,6 +1,7 @@ #include #include +#include #include namespace { @@ -50,3 +51,25 @@ TEST_CASE("envlike concept", "[env]") { static_assert(stdx::envlike>); static_assert(stdx::envlike>); } + +namespace { +template struct match_query { + template using fn = std::is_same; +}; +} // namespace + +TEST_CASE("extending environment doesn't create duplicate keys", "[env]") { + using E1 = stdx::make_env_t; + using E2 = stdx::extend_env_t; + static_assert( + boost::mp11::mp_count_if_q>::value == 1); +} + +TEST_CASE("appending environment doesn't create duplicate keys", "[env]") { + using E1 = stdx::make_env_t; + using E2 = stdx::make_env_t; + using E3 = stdx::make_env_t; + using E = stdx::append_env_t; + static_assert(boost::mp11::mp_count_if_q>::value == + 1); +}