I'm trying to do something similar to C++11 variable number of arguments, same specific type, but I have my own type:
struct Foo
{
Foo(int) {}
Foo(int, int) {}
};
with a bunch of overloads
void f() {}
void f(const Foo&) {}
void f(const Foo&, const Foo&) {}
// etc. ... as many f() overloads as needed ...
works as desired: f(); f(1); f(1, 2); f(1, { 2, 3 });.
Instead of overloads, I can also use std::initializer_list<> with the {} syntax (as suggested here):
void g_(std::initializer_list<Foo>) {}
g_({}); g_({ 1 }); g_({ 1, 2 }); g_({ 1, { 2, 3 } });
but that has an extra set of {} (yeah, it's just two characters). To match the syntax of f() exactly, use a macro:
#define g(...) g_({__VA_ARGS__})
g(); g(1); g(1, 2); g(1,{ 2, 3 });
(Matching the syntax of f() exactly might be needed because of legacy or generated code. ... and it—arguably—just "looks better".)
But I can't find a way to make a variadic template work
void h() { }
template<typename... T>
void h(const Foo&, T...) { }
h(), h(1) and h(1, 2) work, but h(1, {2, 3}) fails to compile because the compiler can't figure out the type of {2, 3} as it can with f() and g_().
Is there a way to make f() work without multiple overloads? Or for g() to work without a macro? g() is very close (only one function and no template magic), but there's that macro ...
{2, 3}has no type, and so cannot be deduced by template deduction.