finished context impl

This commit is contained in:
Patrick 2024-07-28 18:27:12 +02:00
parent 953ad58939
commit 99690fd38b
2 changed files with 139 additions and 99 deletions

View File

@ -60,6 +60,10 @@ consteval std::size_t c_arr_len(T (&arr)[N]) { return N; }
template<typename T>
concept StringLike = std::is_convertible_v<T, std::string_view>;
template<typename T, typename U>
concept not_base_type_same_as = !std::is_same_v<std::remove_cvref_t<T>, std::remove_cvref_t<U>>;
template<std::input_iterator I, std::sentinel_for<I> S, StringLike T>
constexpr bool all_eq_to(I first, S last, T t) {
auto r1 = std::ranges::subrange(first, last);
@ -154,17 +158,36 @@ struct ret_val {
constexpr inline const ret_val_s& operator[](std::size_t i) const { return vals[i]; }
};
template<typename Ctx>
concept ctx_has_type_num = requires {
typename Ctx::type;
{ Ctx::nr } -> std::convertible_to<std::size_t>;
struct ctx_base {};
template<typename T, std::size_t Nr>
struct ctx_tn : ctx_base {
using type = T;
constexpr static std::size_t nr = Nr;
};
template<typename Ctx>
concept ctx_has_type = requires {
typename Ctx::type;
template<typename T>
struct ctx_t : ctx_base {
using type = T;
};
template<std::size_t Nr>
struct ctx_n : ctx_base {
constexpr static std::size_t nr = Nr;
};
template<typename ctx>
concept require_context = requires {
std::is_base_of_v<ctx_base, ctx>;
};
template<typename T> auto create_ctx() { return ctx_t<T>{}; }
template<std::size_t Nr> auto create_ctx() { return ctx_n<Nr>{}; }
template<typename T, std::size_t Nr> auto create_ctx() { return ctx_tn<T, Nr>{}; }
#define CONTEXT(...) decltype(create_ctx<__VA_ARGS__>())
struct empty_param {};
struct test_common_params {
@ -172,61 +195,94 @@ struct test_common_params {
constexpr static auto value = empty_param{};
};
template<typename T, std::size_t Nr = 0>
template<require_context ctx>
struct test_context_params {
using type = T;
constexpr static std::size_t nr = Nr;
using context = ctx;
template<tstring var_name>
constexpr static auto value = empty_param{};
};
template<typename ctx, tstring var_name>
concept param_is_defined = require_context<ctx> && requires {
test_context_params<ctx>::template value<var_name>;
{ test_context_params<ctx>::template value<var_name> } -> not_base_type_same_as<empty_param>;
};
template<typename ctx, tstring var_name>
concept param_is_defined_number_context = require_context<ctx> && requires {
test_context_params<CONTEXT(ctx::nr)>::template value<var_name>;
{ test_context_params<CONTEXT(ctx::nr)>::template value<var_name> } -> not_base_type_same_as<empty_param>;
};
template<typename ctx, tstring var_name>
concept param_is_defined_type_context = require_context<ctx> && requires {
test_context_params<CONTEXT(ctx::type)>::template value<var_name>;
{ test_context_params<CONTEXT(ctx::type)>::template value<var_name> } -> not_base_type_same_as<empty_param>;
};
template<tstring var_name>
concept param_is_defined_common = requires {
test_common_params::value<var_name>;
{ test_common_params::value<var_name> } -> not_base_type_same_as<empty_param>;
};
template<tstring name>
requires param_is_defined_common<name>
constexpr auto& get_test_param() {
return test_common_params::value<name>;
}
template<typename Ctx, tstring name>
requires requires { typename Ctx::type; { Ctx::nr } -> std::convertible_to<std::size_t>; }
template<require_context ctx, tstring name>
requires param_is_defined<ctx, name>
constexpr auto& get_test_param() {
return test_context_params<typename Ctx::type, Ctx::nr>::template value<name>;
return test_context_params<ctx>::template value<name>;
}
template<typename Ctx, tstring name>
requires requires { typename Ctx::type; } && (!requires { Ctx::nr; })
constexpr auto& get_test_param() {
return test_context_params<typename Ctx::type, Ctx::nr>::template value<name>;
template<require_context ctx, tstring name>
requires (!param_is_defined<ctx, name>)
&& param_is_defined_number_context<ctx, name>
&& param_is_defined_type_context<ctx, name>
constexpr void get_test_param() {
throw std::invalid_argument(std::string_view("Could not resolve ambiguous parameter name ") + name);
}
/*template<tstring Name, typename Ctx = void>
struct test_params {
constexpr static auto get() {
if constexpr (requires { typename Ctx::type; }) {
if constexpr (requires { { Ctx::nr } -> std::convertible_to<std::size_t>; }) {
return test_context_params<typename Ctx::type, Ctx::nr>::template value<Name>;
} else {
return test_context_params<typename Ctx::type>::template value<Name>;
}
} else {
return test_common_params::template value<Name>;
}
}
template<require_context ctx, tstring name>
requires (!param_is_defined<ctx, name>)
&& param_is_defined_number_context<ctx, name>
&& (!param_is_defined_type_context<ctx, name>)
constexpr auto& get_test_param() {
return test_context_params<CONTEXT(ctx::nr)>::template value<name>;
}
constexpr static auto get_arr_len() {
if constexpr (requires { typename Ctx::type; }) {
if constexpr (requires { { Ctx::nr } -> std::convertible_to<std::size_t>; }) {
return c_arr_len(test_context_params<typename Ctx::type, Ctx::nr>::template value<Name>);
} else {
return c_arr_len(test_context_params<typename Ctx::type>::template value<Name>);
}
} else {
return c_arr_len(test_common_params::template value<Name>);
}
}
};*/
template<require_context ctx, tstring name>
requires (!param_is_defined<ctx, name>)
&& (!param_is_defined_number_context<ctx, name>)
&& param_is_defined_type_context<ctx, name>
constexpr auto& get_test_param() {
return test_context_params<CONTEXT(ctx::type)>::template value<name>;
}
#define CONTEXT_PARAM(type, name, ...) template<> template<> constexpr type test_context_params<__VA_ARGS__>::value< #name >
#define CONTEXT_PARAM_ARR(type, name, ...) template<> template<> constexpr type test_context_params<__VA_ARGS__>::value< #name >[]
template<require_context ctx, tstring name>
requires (!param_is_defined<ctx, name>) && param_is_defined_common<name>
constexpr auto& get_test_param() {
return test_common_params::value<name>;
}
template<require_context ctx, tstring name>
constexpr void get_test_param() {
throw std::invalid_argument(std::string("Parameter ") + name.value + " could not be found in context");
}
template<tstring name>
constexpr void get_test_param() {
throw std::invalid_argument(std::string("Parameter ") + name.value + " could not be found");
}
#define CONTEXT_PARAM(type, name, ...) template<> template<> constexpr type test_context_params<CONTEXT(__VA_ARGS__)>::value< #name >
#define CONTEXT_PARAM_ARR(type, name, ...) template<> template<> constexpr type test_context_params<CONTEXT(__VA_ARGS__)>::value< #name >[]
class test_definition {
@ -444,30 +500,20 @@ inline std::ostream& operator<<(std::ostream& os, ReturnCode rc) {
template <typename ...Ts>
constexpr auto _repeat_for_types(auto f) {
std::array<ret_val_s, sizeof...(Ts)> rets { (f.template operator()<Ts>())... };
std::array<ret_val_s, sizeof...(Ts)> rets { (f.template operator()<Ts, CONTEXT(Ts)>())... };
return rets;
}
template <std::size_t _N, typename ...Ts, std::size_t N = _N - 1>
template <std::size_t N, typename ...Ts>
constexpr auto _repeat_for_types_n(auto f) {
std::array rets = {
[&]<typename T, std::size_t ...Ns>(std::index_sequence<Ns...>) constexpr {
return std::array {
(f.template operator()<T, Ns, test_context_params<T, Ns>>())...
(f.template operator()<T, Ns, CONTEXT(T, Ns)>())...
};
}.template operator()<Ts>(std::make_index_sequence<N>())...
};
// Clion does not accept this as a constant expression
// even though it compiles and works as intended
//return rets | std::ranges::views::join;
std::array<ret_val_s, sizeof...(Ts) * N> arr;
auto arr_it = std::begin(arr);
for (auto&& rp : rets) {
for (ret_val_s& r : rp) {
*(arr_it++) = r;
}
}
return arr;
return rets | std::ranges::views::join;
}
#define REPEAT_FOR_TYPES(func, ...) { \

View File

@ -3,7 +3,7 @@
#include "test.hpp"
#define GEN_TEST_OBJ_FROM_ARR(nr, i) TestObj(test_context_params<int, nr>::value<"arr">[i], test_context_params<char, nr>::value<"arr">[i], test_context_params<const char *, nr>::value<"arr">[i])
#define GEN_TEST_OBJ_FROM_ARR(nr, i) TestObj(test_context_params<CONTEXT(int, nr)>::value<"arr">[i], test_context_params<CONTEXT(char, nr)>::value<"arr">[i], test_context_params<CONTEXT(const char *, nr)>::value<"arr">[i])
struct TestObj {
int x = 0;
@ -14,18 +14,18 @@ struct TestObj {
};
ADD_TYPE_HINT(TestObj);
template<> template<> constexpr int test_context_params<int, 0>::value<"arr">[] = { 1, 2, 3, 4 };
template<> template<> constexpr int test_context_params<int, 1>::value<"arr">[] = { 5, 6, 7, 8, 9, 10, 11, 12 };
template<> template<> constexpr char test_context_params<char, 0>::value<"arr">[] = { 'a', 'B', 'c', 'D' };
template<> template<> constexpr char test_context_params<char, 1>::value<"arr">[] = { 'e', 'F', 'g', 'H', 'i', 'J', '\n', '\0' };
template<> template<> constexpr const char * test_context_params<const char *, 0>::value<"arr">[] = { "Lorem", "ipsum", "dolor", "sit" };
template<> template<> constexpr const char * test_context_params<const char *, 1>::value<"arr">[] = { "amet", "consetetur", "sadipscing", "elitr", "sed", "diam", "nonumy", "eirmod", "tempor", "\0" };
template<> template<> constexpr TestObj test_context_params<TestObj, 0>::value<"arr">[] = {
template<> template<> constexpr int test_context_params<CONTEXT(int, 0)>::value<"arr">[] = { 1, 2, 3, 4 };
template<> template<> constexpr int test_context_params<CONTEXT(int, 1)>::value<"arr">[] = { 5, 6, 7, 8, 9, 10, 11, 12 };
template<> template<> constexpr char test_context_params<CONTEXT(char, 0)>::value<"arr">[] = { 'a', 'B', 'c', 'D' };
template<> template<> constexpr char test_context_params<CONTEXT(char, 1)>::value<"arr">[] = { 'e', 'F', 'g', 'H', 'i', 'J', '\n', '\0' };
template<> template<> constexpr const char * test_context_params<CONTEXT(const char *, 0)>::value<"arr">[] = { "Lorem", "ipsum", "dolor", "sit" };
template<> template<> constexpr const char * test_context_params<CONTEXT(const char *, 1)>::value<"arr">[] = { "amet", "consetetur", "sadipscing", "elitr", "sed", "diam", "nonumy", "eirmod", "tempor", "\0" };
template<> template<> constexpr TestObj test_context_params<CONTEXT(TestObj, 0)>::value<"arr">[] = {
GEN_TEST_OBJ_FROM_ARR(0, 0),
GEN_TEST_OBJ_FROM_ARR(0, 1),
GEN_TEST_OBJ_FROM_ARR(0, 2),
GEN_TEST_OBJ_FROM_ARR(0, 3) };
template<> template<> constexpr TestObj test_context_params<TestObj, 1>::value<"arr">[] = {
template<> template<> constexpr TestObj test_context_params<CONTEXT(TestObj, 1)>::value<"arr">[] = {
GEN_TEST_OBJ_FROM_ARR(1, 0),
GEN_TEST_OBJ_FROM_ARR(1, 1),
GEN_TEST_OBJ_FROM_ARR(1, 2),
@ -35,18 +35,18 @@ template<> template<> constexpr TestObj test_context_params<TestObj, 1>::value<"
GEN_TEST_OBJ_FROM_ARR(1, 6),
GEN_TEST_OBJ_FROM_ARR(1, 7) };
template<> template<> constexpr std::initializer_list<int> test_context_params<int, 0>::value<"ilist"> = { 1, 2, 3, 4 };
template<> template<> constexpr std::initializer_list<int> test_context_params<int, 1>::value<"ilist"> = { 5, 6, 7, 8, 9, 10, 11, 12 };
template<> template<> constexpr std::initializer_list<char> test_context_params<char, 0>::value<"ilist"> = { 'a', 'B', 'c', 'D' };
template<> template<> constexpr std::initializer_list<char> test_context_params<char, 1>::value<"ilist"> = { 'e', 'F', 'g', 'H', 'i', 'J', '\n', '\0' };
template<> template<> constexpr std::initializer_list<const char *> test_context_params<const char *, 0>::value<"ilist"> = { "Lorem", "ipsum", "dolor", "sit" };
template<> template<> constexpr std::initializer_list<const char *> test_context_params<const char *, 1>::value<"ilist"> = { "amet", "consetetur", "sadipscing", "elitr", "sed", "diam", "nonumy", "eirmod", "tempor", "\0" };
template<> template<> constexpr std::initializer_list<TestObj> test_context_params<TestObj, 0>::value<"ilist"> = {
template<> template<> constexpr std::initializer_list<int> test_context_params<CONTEXT(int, 0)>::value<"ilist"> = { 1, 2, 3, 4 };
template<> template<> constexpr std::initializer_list<int> test_context_params<CONTEXT(int, 1)>::value<"ilist"> = { 5, 6, 7, 8, 9, 10, 11, 12 };
template<> template<> constexpr std::initializer_list<char> test_context_params<CONTEXT(char, 0)>::value<"ilist"> = { 'a', 'B', 'c', 'D' };
template<> template<> constexpr std::initializer_list<char> test_context_params<CONTEXT(char, 1)>::value<"ilist"> = { 'e', 'F', 'g', 'H', 'i', 'J', '\n', '\0' };
template<> template<> constexpr std::initializer_list<const char *> test_context_params<CONTEXT(const char *, 0)>::value<"ilist"> = { "Lorem", "ipsum", "dolor", "sit" };
template<> template<> constexpr std::initializer_list<const char *> test_context_params<CONTEXT(const char *, 1)>::value<"ilist"> = { "amet", "consetetur", "sadipscing", "elitr", "sed", "diam", "nonumy", "eirmod", "tempor", "\0" };
template<> template<> constexpr std::initializer_list<TestObj> test_context_params<CONTEXT(TestObj, 0)>::value<"ilist"> = {
GEN_TEST_OBJ_FROM_ARR(0, 0),
GEN_TEST_OBJ_FROM_ARR(0, 1),
GEN_TEST_OBJ_FROM_ARR(0, 2),
GEN_TEST_OBJ_FROM_ARR(0, 3) };
template<> template<> constexpr std::initializer_list<TestObj> test_context_params<TestObj, 1>::value<"ilist"> = {
template<> template<> constexpr std::initializer_list<TestObj> test_context_params<CONTEXT(TestObj, 1)>::value<"ilist"> = {
GEN_TEST_OBJ_FROM_ARR(1, 0),
GEN_TEST_OBJ_FROM_ARR(1, 1),
GEN_TEST_OBJ_FROM_ARR(1, 2),
@ -56,31 +56,25 @@ template<> template<> constexpr std::initializer_list<TestObj> test_context_para
GEN_TEST_OBJ_FROM_ARR(1, 6),
GEN_TEST_OBJ_FROM_ARR(1, 7) };
template<> template<> constexpr std::size_t test_context_params<int, 0>::value<"capacity"> = 10;
template<> template<> constexpr std::size_t test_context_params<char, 0>::value<"capacity"> = 10;
template<> template<> constexpr std::size_t test_context_params<const char *, 0>::value<"capacity"> = 10;
template<> template<> constexpr std::size_t test_context_params<TestObj, 0>::value<"capacity"> = 10;
template<> template<> constexpr std::size_t test_context_params<int, 1>::value<"capacity"> = 200;
template<> template<> constexpr std::size_t test_context_params<char, 1>::value<"capacity"> = 200;
template<> template<> constexpr std::size_t test_context_params<const char *, 1>::value<"capacity"> = 200;
template<> template<> constexpr std::size_t test_context_params<TestObj, 1>::value<"capacity"> = 200;
template<> template<> constexpr std::size_t test_context_params<CONTEXT(0)>::value<"capacity"> = 10;
template<> template<> constexpr std::size_t test_context_params<CONTEXT(1)>::value<"capacity"> = 200;
template<> template<> constexpr std::size_t test_context_params<int, 0>::value<"size"> = 25;
template<> template<> constexpr std::size_t test_context_params<char, 0>::value<"size"> = 25;
template<> template<> constexpr std::size_t test_context_params<const char *, 0>::value<"size"> = 25;
template<> template<> constexpr std::size_t test_context_params<TestObj, 0>::value<"size"> = 25;
template<> template<> constexpr std::size_t test_context_params<int, 1>::value<"size"> = 50;
template<> template<> constexpr std::size_t test_context_params<char, 1>::value<"size"> = 50;
template<> template<> constexpr std::size_t test_context_params<const char *, 1>::value<"size"> = 50;
template<> template<> constexpr std::size_t test_context_params<TestObj, 1>::value<"size"> = 50;
template<> template<> constexpr std::size_t test_context_params<CONTEXT(int, 0)>::value<"size"> = 25;
template<> template<> constexpr std::size_t test_context_params<CONTEXT(char, 0)>::value<"size"> = 25;
template<> template<> constexpr std::size_t test_context_params<CONTEXT(const char *, 0)>::value<"size"> = 25;
template<> template<> constexpr std::size_t test_context_params<CONTEXT(TestObj, 0)>::value<"size"> = 25;
template<> template<> constexpr std::size_t test_context_params<CONTEXT(int, 1)>::value<"size"> = 50;
template<> template<> constexpr std::size_t test_context_params<CONTEXT(char, 1)>::value<"size"> = 50;
template<> template<> constexpr std::size_t test_context_params<CONTEXT(const char *, 1)>::value<"size"> = 50;
template<> template<> constexpr std::size_t test_context_params<CONTEXT(TestObj, 1)>::value<"size"> = 50;
template<> template<> constexpr int test_context_params<int, 0>::value<"value"> = 5;
template<> template<> constexpr int test_context_params<int, 1>::value<"value"> = INT_MIN;
template<> template<> constexpr char test_context_params<char, 0>::value<"value"> = 'P';
template<> template<> constexpr char test_context_params<char, 1>::value<"value"> = CHAR_MAX;
template<> template<> constexpr const char * test_context_params<const char *, 0>::value<"value"> = "Test string 1";
template<> template<> constexpr const char * test_context_params<const char *, 1>::value<"value"> = "Test string 2";
template<> template<> constexpr TestObj test_context_params<TestObj, 0>::value<"value"> = TestObj(5, 'P', "Object String 1");
template<> template<> constexpr TestObj test_context_params<TestObj, 1>::value<"value"> = TestObj(INT_MAX, 'p', "2 Object String");
template<> template<> constexpr int test_context_params<CONTEXT(int, 0)>::value<"value"> = 5;
template<> template<> constexpr int test_context_params<CONTEXT(int, 1)>::value<"value"> = INT_MIN;
template<> template<> constexpr char test_context_params<CONTEXT(char, 0)>::value<"value"> = 'P';
template<> template<> constexpr char test_context_params<CONTEXT(char, 1)>::value<"value"> = CHAR_MAX;
template<> template<> constexpr const char * test_context_params<CONTEXT(const char *, 0)>::value<"value"> = "Test string 1";
template<> template<> constexpr const char * test_context_params<CONTEXT(const char *, 1)>::value<"value"> = "Test string 2";
template<> template<> constexpr TestObj test_context_params<CONTEXT(TestObj, 0)>::value<"value"> = TestObj(5, 'P', "Object String 1");
template<> template<> constexpr TestObj test_context_params<CONTEXT(TestObj, 1)>::value<"value"> = TestObj(INT_MAX, 'p', "2 Object String");
#endif //CONST_CONTAINER_TEST_ARGS_H