make converter able to take a tuple as conversion argument

This commit is contained in:
ado 2020-12-19 14:41:19 +01:00
parent 508e091469
commit 879c726964
4 changed files with 27 additions and 13 deletions

View File

@ -81,6 +81,11 @@ struct no_void_validator_tup {
using type = no_validator_tup_t<no_void_tup_t<Ts...>>; using type = no_validator_tup_t<no_void_tup_t<Ts...>>;
}; };
template <typename... Ts>
struct no_void_validator_tup<std::tuple<Ts...>> {
using type = no_validator_tup_t<no_void_tup_t<Ts...>>;
};
template <typename... Ts> template <typename... Ts>
using no_void_validator_tup_t = typename no_void_validator_tup<Ts...>::type; using no_void_validator_tup_t = typename no_void_validator_tup<Ts...>::type;
@ -152,6 +157,10 @@ class converter {
return to_object<T>( return to_object<T>(
convert_impl(elems, (arg_tuple*){})); convert_impl(elems, (arg_tuple*){}));
} else if constexpr (sizeof...(Ts) == 0 &&
is_instance_of<T, std::tuple>::value) {
return convert_impl(elems, (T*){});
} else { } else {
return convert_impl<T, Ts...>(elems); return convert_impl<T, Ts...>(elems);
} }
@ -337,11 +346,11 @@ class converter {
using elem_t = std::tuple_element_t<ArgN, std::tuple<Ts...>>; using elem_t = std::tuple_element_t<ArgN, std::tuple<Ts...>>;
constexpr bool not_void = !std::is_void_v<elem_t>; constexpr bool not_void = !std::is_void_v<elem_t>;
constexpr bool not_tuple = constexpr bool one_element =
count_not<std::is_void, Ts...>::size == 1; count_not<std::is_void, Ts...>::size == 1;
if constexpr (not_void) { if constexpr (not_void) {
if constexpr (not_tuple) { if constexpr (one_element) {
extract_one<elem_t>(tup, elems[ArgN], ArgN); extract_one<elem_t>(tup, elems[ArgN], ArgN);
} else { } else {
auto& el = std::get<TupN>(tup); auto& el = std::get<TupN>(tup);
@ -359,7 +368,6 @@ class converter {
no_void_validator_tup_t<Ts...> extract_tuple(const split_input& elems) { no_void_validator_tup_t<Ts...> extract_tuple(const split_input& elems) {
static_assert(!all_of<std::is_void, Ts...>::value, static_assert(!all_of<std::is_void, Ts...>::value,
"at least one parameter must be non void"); "at least one parameter must be non void");
no_void_validator_tup_t<Ts...> ret; no_void_validator_tup_t<Ts...> ret;
extract_multiple<0, 0, Ts...>(ret, elems); extract_multiple<0, 0, Ts...>(ret, elems);
return ret; return ret;

View File

@ -115,7 +115,7 @@ class parser {
return composite_with(std::move(value)); return composite_with(std::move(value));
} }
auto values() { std::tuple<Ts...> values() {
return values_; return values_;
} }
@ -198,10 +198,13 @@ class parser {
// failed // failed
template <typename Arg, typename Fun = None> template <typename Arg, typename Fun = None>
void try_invoke(Arg&& arg, Fun&& fun) { void try_invoke(Arg&& arg, Fun&& fun) {
if constexpr (!std::is_same_v<std::decay_t<Fun>, None>) { constexpr bool is_none =
std::is_same_v<std::decay_t<Fun>, None>;
if constexpr (!is_none) {
using Ret = decltype( using Ret = decltype(
try_invoke_impl(arg, std::forward<Fun>(fun))); try_invoke_impl(arg, std::forward<Fun>(fun)));
if constexpr (!std::is_same_v<Ret, void>) { constexpr bool returns_void = std::is_same_v<Ret, void>;
if constexpr (!returns_void) {
if (!try_invoke_impl(arg, if (!try_invoke_impl(arg,
std::forward<Fun>(fun))) { std::forward<Fun>(fun))) {
set_error_failed_check(); set_error_failed_check();
@ -219,7 +222,9 @@ class parser {
// laid out as a parameter pack // laid out as a parameter pack
template <typename Arg, typename Fun = None> template <typename Arg, typename Fun = None>
auto try_invoke_impl(Arg&& arg, Fun&& fun) { auto try_invoke_impl(Arg&& arg, Fun&& fun) {
if constexpr (!std::is_same_v<Fun, None>) { constexpr bool is_none =
std::is_same_v<std::decay_t<Fun>, None>;
if constexpr (!is_none) {
if constexpr (std::is_invocable_v<Fun>) { if constexpr (std::is_invocable_v<Fun>) {
return fun(); return fun();
} else if constexpr (std::is_invocable_v<Fun, Arg>) { } else if constexpr (std::is_invocable_v<Fun, Arg>) {

View File

@ -312,13 +312,13 @@ struct none_of<Trait, std::tuple<Ts...>> {
// is instance of // is instance of
//////////////// ////////////////
template <typename, template <class> class> template <typename T, template <typename...> class Template>
struct is_instance_of { struct is_instance_of {
constexpr static bool value = false; constexpr static bool value = false;
}; };
template <typename T, template <class> class U> template <typename ...Ts, template <typename...> class Template>
struct is_instance_of<U<T>, U> { struct is_instance_of<Template<Ts...>, Template> {
constexpr static bool value = true; constexpr static bool value = true;
}; };

View File

@ -217,7 +217,7 @@ TEST_CASE("testing the moving of parsed values") {
ss::parser p{f.name, ","}; ss::parser p{f.name, ","};
auto x = p.get_next<my_string, my_string, my_string>(); auto x = p.get_next<my_string, my_string, my_string>();
CHECK(copy_called == 0); CHECK(copy_called == 0);
CHECK(move_called == 3 * move_called_one_col); CHECK(move_called <= 3 * move_called_one_col);
move_called = copy_called = 0; move_called = copy_called = 0;
} }
@ -225,7 +225,8 @@ TEST_CASE("testing the moving of parsed values") {
ss::parser p{f.name, ","}; ss::parser p{f.name, ","};
auto x = p.get_object<Y, my_string, my_string, my_string>(); auto x = p.get_object<Y, my_string, my_string, my_string>();
CHECK(copy_called == 0); CHECK(copy_called == 0);
CHECK(move_called == 6 * move_called_one_col); CHECK(move_called <= 6 * move_called_one_col);
std::cout << move_called << std::endl;
move_called = copy_called = 0; move_called = copy_called = 0;
} }
@ -233,7 +234,7 @@ TEST_CASE("testing the moving of parsed values") {
ss::parser p{f.name, ","}; ss::parser p{f.name, ","};
auto x = p.get_next<Y>(); auto x = p.get_next<Y>();
CHECK(copy_called == 0); CHECK(copy_called == 0);
CHECK(move_called == 6 * move_called_one_col); CHECK(move_called <= 6 * move_called_one_col);
move_called = copy_called = 0; move_called = copy_called = 0;
} }
} }