From a6ebfcb236a1754cec6d10212b4848f3f6ca52ef Mon Sep 17 00:00:00 2001 From: Ben Deane Date: Tue, 4 Mar 2025 15:51:11 -0700 Subject: [PATCH] :sparkles: Add useful things for environment handling Problem: - There is no way to override one environment with another. - There is no concept to identify an environment type. Solution: - Add `append_env_t`. - Add `envlike`. --- include/stdx/env.hpp | 23 +++++++++++++++-------- test/env.cpp | 18 +++++++++++++----- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/include/stdx/env.hpp b/include/stdx/env.hpp index 8c7b0a5..aae4e3d 100644 --- a/include/stdx/env.hpp +++ b/include/stdx/env.hpp @@ -4,18 +4,19 @@ #include #include +#include #include namespace stdx { inline namespace v1 { +namespace _env { template struct ct_prop { [[nodiscard]] CONSTEVAL static auto query(decltype(Query)) noexcept { return Value; } }; -namespace _env { template concept valid_query_for = requires(Env const &e) { e.query(Q{}); }; @@ -38,6 +39,9 @@ template struct env { } }; +template +concept envlike = is_specialization_of_v; + namespace _env { template struct autowrap { // NOLINTNEXTLINE(google-explicit-constructor) @@ -64,14 +68,14 @@ template struct wrap { template struct for_each_pair; template struct for_each_pair> { template - using type = - env...>, - 2 * Is>::value.value, - boost::mp11::mp_at_c...>, - (2 * Is) + 1>::value.value>...>; + using type = env< + _env::ct_prop...>, + 2 * Is>::value.value, + boost::mp11::mp_at_c...>, + (2 * Is) + 1>::value.value>...>; }; -template > +template > constexpr auto make_env = [] { using new_env_t = typename for_each_pair< std::make_index_sequence>::template type; @@ -79,10 +83,13 @@ constexpr auto make_env = [] { }; } // namespace _env -template +template using extend_env_t = decltype(_env::make_env.template operator()()); +template +using append_env_t = boost::mp11::mp_reverse>; + template <_env::autowrap... Args> using make_env_t = extend_env_t, Args...>; } // namespace v1 diff --git a/test/env.cpp b/test/env.cpp index 61700fa..2a72559 100644 --- a/test/env.cpp +++ b/test/env.cpp @@ -21,11 +21,6 @@ TEST_CASE("lookup query with default", "[env]") { static_assert(custom(stdx::env<>{}) == 42); } -TEST_CASE("lookup with single-value prop", "[env]") { - using E = stdx::ct_prop; - static_assert(custom(E{}) == 17); -} - TEST_CASE("make an environment", "[env]") { using E = stdx::make_env_t; static_assert(custom(E{}) == 17); @@ -37,8 +32,21 @@ TEST_CASE("extend an environment", "[env]") { static_assert(custom(E2{}) == 18); } +TEST_CASE("append an environment", "[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(custom(E{}) == 19); +} + TEST_CASE("environment converts string literals to ct_string", "[env]") { using namespace stdx::literals; using E = stdx::make_env_t; static_assert(custom(E{}) == "hello"_cts); } + +TEST_CASE("envlike concept", "[env]") { + static_assert(stdx::envlike>); + static_assert(stdx::envlike>); +}