I have the following class template:
template<class T, unsigned N>
class MyClass;
where T
is some type, N
- number of components. It is possible to initialize the class using MyClass{a1, a2, a3}
where the number of arguments is equal to N
.
I want to add a member function template (let's name it foo
) of MyClass
that would meet the following requirements:
- It is templated by another type
T2
(i.e.template<class T2> void foo(..)
) - It accepts enough data to construct
MyClass<T,N>
, but not less and not more. Violating this results in a compile-time error. - It deduces
T2
from the types of the parameters. I.e. I want that it would be possible to callfoo({a1, a2, a3})
orfoo(a1, a2, a3)
or similar, without typing<double>
orMyClass<double,N>
every time.
Is there a way to implement the function so that the above requirements are satisfied?
I've already thought about and/or tried the following solutions:
1) The obvious one:
...
template<class T2>
void foo(MyClass<T2, N> arg);
...
a.foo({1,2,3}); //compile-time error
Can't work in principle, because braced initializer lists are a non-deduced context, thus they can't deduce any types. That's quite unfortunate, I'd be very happy if this worked.
2) initializer_list
Can't work in principle, because it can't check the number of arguments at compile-time.
3) Variadic template magic
Something like the function below would be neat:
template<class...T2, class std::enable_if<sizeof...(T2) == N, int>::type = 0>
void foo(T2... args);
..
foo(1,2,3);
However, I couldn't get it to work - T2 still couldn't be deduced. Maybe someone knows why? I used GCC4.7 20120121 snapshot.
4) The ugly one
Essentially this is the same as the above one, just expanded into several overloads for different N. I would better reimplement MyClass
as a set of specializations for different N
s than to use this one.
template<class T2, class std::enable_if<N == 1, int>::type = 0>
void fun(T2 a1); //if N == 1
template<class T2, ..>
void fun(T2 a1, T2 a2); //if N == 2
template<class T2, ..>
void fun(T2 a1, T2 a2, T2 a3); //if N == 3
...