diff --git a/test/common_helper/test.hpp b/test/common_helper/test.hpp index a0d7937..9677502 100644 --- a/test/common_helper/test.hpp +++ b/test/common_helper/test.hpp @@ -60,6 +60,10 @@ consteval std::size_t c_arr_len(T (&arr)[N]) { return N; } template concept StringLike = std::is_convertible_v; +template +concept not_base_type_same_as = !std::is_same_v, std::remove_cvref_t>; + + template 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 -concept ctx_has_type_num = requires { - typename Ctx::type; - { Ctx::nr } -> std::convertible_to; +struct ctx_base {}; + +template +struct ctx_tn : ctx_base { + using type = T; + constexpr static std::size_t nr = Nr; }; -template -concept ctx_has_type = requires { - typename Ctx::type; +template +struct ctx_t : ctx_base { + using type = T; }; +template +struct ctx_n : ctx_base { + constexpr static std::size_t nr = Nr; +}; + +template +concept require_context = requires { + std::is_base_of_v; +}; + +template auto create_ctx() { return ctx_t{}; } +template auto create_ctx() { return ctx_n{}; } +template auto create_ctx() { return ctx_tn{}; } + +#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 +template struct test_context_params { - using type = T; - constexpr static std::size_t nr = Nr; + using context = ctx; template constexpr static auto value = empty_param{}; }; +template +concept param_is_defined = require_context && requires { + test_context_params::template value; + { test_context_params::template value } -> not_base_type_same_as; +}; + +template +concept param_is_defined_number_context = require_context && requires { + test_context_params::template value; + { test_context_params::template value } -> not_base_type_same_as; +}; + +template +concept param_is_defined_type_context = require_context && requires { + test_context_params::template value; + { test_context_params::template value } -> not_base_type_same_as; +}; + +template +concept param_is_defined_common = requires { + test_common_params::value; + { test_common_params::value } -> not_base_type_same_as; +}; + + template + requires param_is_defined_common constexpr auto& get_test_param() { return test_common_params::value; } -template - requires requires { typename Ctx::type; { Ctx::nr } -> std::convertible_to; } +template + requires param_is_defined constexpr auto& get_test_param() { - return test_context_params::template value; + return test_context_params::template value; } -template - requires requires { typename Ctx::type; } && (!requires { Ctx::nr; }) -constexpr auto& get_test_param() { - return test_context_params::template value; +template + requires (!param_is_defined) + && param_is_defined_number_context + && param_is_defined_type_context +constexpr void get_test_param() { + throw std::invalid_argument(std::string_view("Could not resolve ambiguous parameter name ") + name); } -/*template -struct test_params { - constexpr static auto get() { - if constexpr (requires { typename Ctx::type; }) { - if constexpr (requires { { Ctx::nr } -> std::convertible_to; }) { - return test_context_params::template value; - } else { - return test_context_params::template value; - } - } else { - return test_common_params::template value; - } - } +template + requires (!param_is_defined) + && param_is_defined_number_context + && (!param_is_defined_type_context) +constexpr auto& get_test_param() { + return test_context_params::template value; +} - constexpr static auto get_arr_len() { - if constexpr (requires { typename Ctx::type; }) { - if constexpr (requires { { Ctx::nr } -> std::convertible_to; }) { - return c_arr_len(test_context_params::template value); - } else { - return c_arr_len(test_context_params::template value); - } - } else { - return c_arr_len(test_common_params::template value); - } - } -};*/ +template + requires (!param_is_defined) + && (!param_is_defined_number_context) + && param_is_defined_type_context +constexpr auto& get_test_param() { + return test_context_params::template value; +} -#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 + requires (!param_is_defined) && param_is_defined_common +constexpr auto& get_test_param() { + return test_common_params::value; +} + +template +constexpr void get_test_param() { + throw std::invalid_argument(std::string("Parameter ") + name.value + " could not be found in context"); +} + +template +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::value< #name > +#define CONTEXT_PARAM_ARR(type, name, ...) template<> template<> constexpr type test_context_params::value< #name >[] class test_definition { @@ -444,30 +500,20 @@ inline std::ostream& operator<<(std::ostream& os, ReturnCode rc) { template constexpr auto _repeat_for_types(auto f) { - std::array rets { (f.template operator()())... }; + std::array rets { (f.template operator()())... }; return rets; } -template +template constexpr auto _repeat_for_types_n(auto f) { std::array rets = { [&](std::index_sequence) constexpr { return std::array { - (f.template operator()>())... + (f.template operator()())... }; }.template operator()(std::make_index_sequence())... }; - // 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 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, ...) { \ diff --git a/test/const_vector/test_params.h b/test/const_vector/test_params.h index dce133b..5ad5d0f 100644 --- a/test/const_vector/test_params.h +++ b/test/const_vector/test_params.h @@ -3,7 +3,7 @@ #include "test.hpp" -#define GEN_TEST_OBJ_FROM_ARR(nr, i) TestObj(test_context_params::value<"arr">[i], test_context_params::value<"arr">[i], test_context_params::value<"arr">[i]) +#define GEN_TEST_OBJ_FROM_ARR(nr, i) TestObj(test_context_params::value<"arr">[i], test_context_params::value<"arr">[i], test_context_params::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::value<"arr">[] = { 1, 2, 3, 4 }; -template<> template<> constexpr int test_context_params::value<"arr">[] = { 5, 6, 7, 8, 9, 10, 11, 12 }; -template<> template<> constexpr char test_context_params::value<"arr">[] = { 'a', 'B', 'c', 'D' }; -template<> template<> constexpr char test_context_params::value<"arr">[] = { 'e', 'F', 'g', 'H', 'i', 'J', '\n', '\0' }; -template<> template<> constexpr const char * test_context_params::value<"arr">[] = { "Lorem", "ipsum", "dolor", "sit" }; -template<> template<> constexpr const char * test_context_params::value<"arr">[] = { "amet", "consetetur", "sadipscing", "elitr", "sed", "diam", "nonumy", "eirmod", "tempor", "\0" }; -template<> template<> constexpr TestObj test_context_params::value<"arr">[] = { +template<> template<> constexpr int test_context_params::value<"arr">[] = { 1, 2, 3, 4 }; +template<> template<> constexpr int test_context_params::value<"arr">[] = { 5, 6, 7, 8, 9, 10, 11, 12 }; +template<> template<> constexpr char test_context_params::value<"arr">[] = { 'a', 'B', 'c', 'D' }; +template<> template<> constexpr char test_context_params::value<"arr">[] = { 'e', 'F', 'g', 'H', 'i', 'J', '\n', '\0' }; +template<> template<> constexpr const char * test_context_params::value<"arr">[] = { "Lorem", "ipsum", "dolor", "sit" }; +template<> template<> constexpr const char * test_context_params::value<"arr">[] = { "amet", "consetetur", "sadipscing", "elitr", "sed", "diam", "nonumy", "eirmod", "tempor", "\0" }; +template<> template<> constexpr TestObj test_context_params::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::value<"arr">[] = { +template<> template<> constexpr TestObj test_context_params::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::value<" GEN_TEST_OBJ_FROM_ARR(1, 6), GEN_TEST_OBJ_FROM_ARR(1, 7) }; -template<> template<> constexpr std::initializer_list test_context_params::value<"ilist"> = { 1, 2, 3, 4 }; -template<> template<> constexpr std::initializer_list test_context_params::value<"ilist"> = { 5, 6, 7, 8, 9, 10, 11, 12 }; -template<> template<> constexpr std::initializer_list test_context_params::value<"ilist"> = { 'a', 'B', 'c', 'D' }; -template<> template<> constexpr std::initializer_list test_context_params::value<"ilist"> = { 'e', 'F', 'g', 'H', 'i', 'J', '\n', '\0' }; -template<> template<> constexpr std::initializer_list test_context_params::value<"ilist"> = { "Lorem", "ipsum", "dolor", "sit" }; -template<> template<> constexpr std::initializer_list test_context_params::value<"ilist"> = { "amet", "consetetur", "sadipscing", "elitr", "sed", "diam", "nonumy", "eirmod", "tempor", "\0" }; -template<> template<> constexpr std::initializer_list test_context_params::value<"ilist"> = { +template<> template<> constexpr std::initializer_list test_context_params::value<"ilist"> = { 1, 2, 3, 4 }; +template<> template<> constexpr std::initializer_list test_context_params::value<"ilist"> = { 5, 6, 7, 8, 9, 10, 11, 12 }; +template<> template<> constexpr std::initializer_list test_context_params::value<"ilist"> = { 'a', 'B', 'c', 'D' }; +template<> template<> constexpr std::initializer_list test_context_params::value<"ilist"> = { 'e', 'F', 'g', 'H', 'i', 'J', '\n', '\0' }; +template<> template<> constexpr std::initializer_list test_context_params::value<"ilist"> = { "Lorem", "ipsum", "dolor", "sit" }; +template<> template<> constexpr std::initializer_list test_context_params::value<"ilist"> = { "amet", "consetetur", "sadipscing", "elitr", "sed", "diam", "nonumy", "eirmod", "tempor", "\0" }; +template<> template<> constexpr std::initializer_list test_context_params::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 test_context_params::value<"ilist"> = { +template<> template<> constexpr std::initializer_list test_context_params::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 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::value<"capacity"> = 10; -template<> template<> constexpr std::size_t test_context_params::value<"capacity"> = 10; -template<> template<> constexpr std::size_t test_context_params::value<"capacity"> = 10; -template<> template<> constexpr std::size_t test_context_params::value<"capacity"> = 10; -template<> template<> constexpr std::size_t test_context_params::value<"capacity"> = 200; -template<> template<> constexpr std::size_t test_context_params::value<"capacity"> = 200; -template<> template<> constexpr std::size_t test_context_params::value<"capacity"> = 200; -template<> template<> constexpr std::size_t test_context_params::value<"capacity"> = 200; +template<> template<> constexpr std::size_t test_context_params::value<"capacity"> = 10; +template<> template<> constexpr std::size_t test_context_params::value<"capacity"> = 200; -template<> template<> constexpr std::size_t test_context_params::value<"size"> = 25; -template<> template<> constexpr std::size_t test_context_params::value<"size"> = 25; -template<> template<> constexpr std::size_t test_context_params::value<"size"> = 25; -template<> template<> constexpr std::size_t test_context_params::value<"size"> = 25; -template<> template<> constexpr std::size_t test_context_params::value<"size"> = 50; -template<> template<> constexpr std::size_t test_context_params::value<"size"> = 50; -template<> template<> constexpr std::size_t test_context_params::value<"size"> = 50; -template<> template<> constexpr std::size_t test_context_params::value<"size"> = 50; +template<> template<> constexpr std::size_t test_context_params::value<"size"> = 25; +template<> template<> constexpr std::size_t test_context_params::value<"size"> = 25; +template<> template<> constexpr std::size_t test_context_params::value<"size"> = 25; +template<> template<> constexpr std::size_t test_context_params::value<"size"> = 25; +template<> template<> constexpr std::size_t test_context_params::value<"size"> = 50; +template<> template<> constexpr std::size_t test_context_params::value<"size"> = 50; +template<> template<> constexpr std::size_t test_context_params::value<"size"> = 50; +template<> template<> constexpr std::size_t test_context_params::value<"size"> = 50; -template<> template<> constexpr int test_context_params::value<"value"> = 5; -template<> template<> constexpr int test_context_params::value<"value"> = INT_MIN; -template<> template<> constexpr char test_context_params::value<"value"> = 'P'; -template<> template<> constexpr char test_context_params::value<"value"> = CHAR_MAX; -template<> template<> constexpr const char * test_context_params::value<"value"> = "Test string 1"; -template<> template<> constexpr const char * test_context_params::value<"value"> = "Test string 2"; -template<> template<> constexpr TestObj test_context_params::value<"value"> = TestObj(5, 'P', "Object String 1"); -template<> template<> constexpr TestObj test_context_params::value<"value"> = TestObj(INT_MAX, 'p', "2 Object String"); +template<> template<> constexpr int test_context_params::value<"value"> = 5; +template<> template<> constexpr int test_context_params::value<"value"> = INT_MIN; +template<> template<> constexpr char test_context_params::value<"value"> = 'P'; +template<> template<> constexpr char test_context_params::value<"value"> = CHAR_MAX; +template<> template<> constexpr const char * test_context_params::value<"value"> = "Test string 1"; +template<> template<> constexpr const char * test_context_params::value<"value"> = "Test string 2"; +template<> template<> constexpr TestObj test_context_params::value<"value"> = TestObj(5, 'P', "Object String 1"); +template<> template<> constexpr TestObj test_context_params::value<"value"> = TestObj(INT_MAX, 'p', "2 Object String"); #endif //CONST_CONTAINER_TEST_ARGS_H