Skip to content

Commit 7ffe3f6

Browse files
authored
Merge pull request #202 from elbeno/more-env
2 parents 68316e8 + a6ebfcb commit 7ffe3f6

File tree

2 files changed

+28
-13
lines changed

2 files changed

+28
-13
lines changed

include/stdx/env.hpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,19 @@
44

55
#include <stdx/compiler.hpp>
66
#include <stdx/ct_string.hpp>
7+
#include <stdx/type_traits.hpp>
78

89
#include <boost/mp11/algorithm.hpp>
910

1011
namespace stdx {
1112
inline namespace v1 {
13+
namespace _env {
1214
template <auto Query, auto Value> struct ct_prop {
1315
[[nodiscard]] CONSTEVAL static auto query(decltype(Query)) noexcept {
1416
return Value;
1517
}
1618
};
1719

18-
namespace _env {
1920
template <typename Q, typename Env>
2021
concept valid_query_for = requires(Env const &e) { e.query(Q{}); };
2122

@@ -38,6 +39,9 @@ template <typename... Envs> struct env {
3839
}
3940
};
4041

42+
template <typename T>
43+
concept envlike = is_specialization_of_v<T, env>;
44+
4145
namespace _env {
4246
template <typename T> struct autowrap {
4347
// NOLINTNEXTLINE(google-explicit-constructor)
@@ -64,25 +68,28 @@ template <auto V> struct wrap {
6468
template <typename> struct for_each_pair;
6569
template <std::size_t... Is> struct for_each_pair<std::index_sequence<Is...>> {
6670
template <auto... Args>
67-
using type =
68-
env<ct_prop<boost::mp11::mp_at_c<boost::mp11::mp_list<wrap<Args>...>,
69-
2 * Is>::value.value,
70-
boost::mp11::mp_at_c<boost::mp11::mp_list<wrap<Args>...>,
71-
(2 * Is) + 1>::value.value>...>;
71+
using type = env<
72+
_env::ct_prop<boost::mp11::mp_at_c<boost::mp11::mp_list<wrap<Args>...>,
73+
2 * Is>::value.value,
74+
boost::mp11::mp_at_c<boost::mp11::mp_list<wrap<Args>...>,
75+
(2 * Is) + 1>::value.value>...>;
7276
};
7377

74-
template <typename Env = env<>>
78+
template <envlike Env = env<>>
7579
constexpr auto make_env = []<autowrap... Args> {
7680
using new_env_t = typename for_each_pair<
7781
std::make_index_sequence<sizeof...(Args) / 2>>::template type<Args...>;
7882
return boost::mp11::mp_append<new_env_t, Env>{};
7983
};
8084
} // namespace _env
8185

82-
template <typename Env, _env::autowrap... Args>
86+
template <envlike Env, _env::autowrap... Args>
8387
using extend_env_t =
8488
decltype(_env::make_env<Env>.template operator()<Args...>());
8589

90+
template <envlike... Envs>
91+
using append_env_t = boost::mp11::mp_reverse<boost::mp11::mp_append<Envs...>>;
92+
8693
template <_env::autowrap... Args>
8794
using make_env_t = extend_env_t<env<>, Args...>;
8895
} // namespace v1

test/env.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,6 @@ TEST_CASE("lookup query with default", "[env]") {
2121
static_assert(custom(stdx::env<>{}) == 42);
2222
}
2323

24-
TEST_CASE("lookup with single-value prop", "[env]") {
25-
using E = stdx::ct_prop<custom, 17>;
26-
static_assert(custom(E{}) == 17);
27-
}
28-
2924
TEST_CASE("make an environment", "[env]") {
3025
using E = stdx::make_env_t<custom, 17>;
3126
static_assert(custom(E{}) == 17);
@@ -37,8 +32,21 @@ TEST_CASE("extend an environment", "[env]") {
3732
static_assert(custom(E2{}) == 18);
3833
}
3934

35+
TEST_CASE("append an environment", "[env]") {
36+
using E1 = stdx::make_env_t<custom, 17>;
37+
using E2 = stdx::make_env_t<custom, 18>;
38+
using E3 = stdx::make_env_t<custom, 19>;
39+
using E = stdx::append_env_t<E1, E2, E3>;
40+
static_assert(custom(E{}) == 19);
41+
}
42+
4043
TEST_CASE("environment converts string literals to ct_string", "[env]") {
4144
using namespace stdx::literals;
4245
using E = stdx::make_env_t<custom, "hello">;
4346
static_assert(custom(E{}) == "hello"_cts);
4447
}
48+
49+
TEST_CASE("envlike concept", "[env]") {
50+
static_assert(stdx::envlike<stdx::env<>>);
51+
static_assert(stdx::envlike<stdx::make_env_t<custom, 17>>);
52+
}

0 commit comments

Comments
 (0)