How to deduce template multiple variadic parameters and using as std::tuple as following code ? when compile, gets "'f': function does not take 5 arguments" error.
#include <tuple>
struct Type1 {
int v = 0;
};
struct Type2 {
int v = 0;
};
template <typename ..._t1, typename ..._t2>
void f(
_t1... t1,
_t2... t2) {
// t1 as a, b, c
// t2 as d, e
auto x = std::tuple<_t1...>(t1...);
auto y = std::tuple<_t2...>(t2...);
}
int main(int argc, char *argv[]) {
Type1 a, b, c;
Type2 d, e;
// |-- _t1 --| |-- _t2 --|
f( a, b, c, d, e); // 'f': function does not take 5 arguments
return 0;
}
CodePudding user response:
It is not possible to unambiguously deduce _t1
and _t2
from the 5 parameters you pass to the function. The compiler cannot know if 0
or all 5
of the parameters belong to _t1
or _t2
.
This is much simpler if the function has tuple arguments:
#include <tuple>
struct Type1 { int v = 0; };
struct Type2 { int v = 0; };
template <typename... _t1, typename... _t2>
void f( std::tuple<_t1...> t1, std::tuple<_t2...> t2) {}
int main() {
Type1 a, b, c;
Type2 d, e;
f(std::make_tuple(a, b, c),std::make_tuple( d, e));
}
This is also a way to go for the more general question:
how to deduce template multiple variadic parameters?
If you wrap them in a tuple (or other variadic template) you can get both packs deduced. If you don't like std::make_tuple
you can follow the suggestion of Jarod42 and instead use
template <typename T1, typename T2>
void f( std::initializer_list<t1>, std::initializer_list<t2>)
However, this assumes that there are only two different types involved. Perhaps thats what you wanted in the first place.
CodePudding user response:
There is a lambda trick to get a succinct syntax:
template<typename... T1>
auto f(T1... t1) {
return [=](auto... t2) {
auto x = std::tuple(t1...);
auto y = std::tuple(t2...);
// ...
};
}
Type1 a, b, c;
Type2 d, e;
f(a, b, c)(d, e);