I have a helper function f
that receives a variadic number of tuple-like arguments, but I'd be okay restricting it to std::tuple
. These are in practice always temporaries, so a typical call looks something like this:
int i{};
f(
std::tuple{"hello",2},
std::tuple{"world","!",3},
std::tie ("!",i)
//^^^^^^^^^^
);
The function template looks (simplified) something like this:
template <typename... T>
void f(T&&... t) {
// do stuff with t...
}
Problem
The issue I have with this is that I want to remove the need for the caller to restate that each argument is a tuple because it is redundant --- so I want a call of the form:
// goal
f(
{"hello",2},
{"world","!",3},
{"!",std::ref(i)}
);
Unfortunately, deducing this type appears to be impossible, even if I contract f
down to accepting only something like template <Tuple... T>
where Tuple
only admits types like std::tuple<Args...>
.
Some attempts
The only type that can somewhat deduce its nested template arguments is std::initializer_list
as in:
template <typename... T>
void g(std::initializer_list<T>...) {}
// call:
g({1,2}, {"hello","world","!"}); // fine
Alas, that supports only homogeneous values in each argument, whereas f
's arguments are composed of heterogeneous values (e.g. char const*
and int
). To my understanding this works because std::initializer_list
is magic in that it has language support. So, we probably cannot recreate that behaviour on a different type.
I even briefly considered making each argument a tuple of std::any
but the individual arguments may have a different number of values.
Question
Is there a way to achieve a call as shown in the code snippet labelled "goal"?
It would be okay if I have to write my own argument type instead of using std::tuple
, although I don't see how that would help.