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:
T2
(i.e. template<class T2> void foo(..)
)MyClass<T,N>
, but not less and not more. Violating this results in a compile-time error.T2
from the types of the parameters. I.e. I want that it would be possible to call foo({a1, a2, a3})
or foo(a1, a2, a3)
or similar, without typing <double>
or MyClass<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
...
Function Templates with Multiple Parameters You can also use multiple parameters in your function template.
Member function templates are function templates that are members of a class or class template.
In C++ this can be achieved using template parameters. A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.
Template classes and functions can make use of another kind of template parameter known as a non-type parameter. A template non-type parameter is a template parameter where the type of the parameter is predefined and is substituted for a constexpr value passed in as an argument.
Your third variant's second non-type param should have prefix typename
not class
:
template<class...T2, typename std::enable_if<sizeof...(T2) == N, int>::type = 0>
void foo(T2... args);
..
foo(1,2,3);
Check it
Gcc 4.7.0 snapshots has some bugs with templates I guess, if you try it with gcc 4.6.2/1 it shall work.
Why not use a static_assert
?
template <typename T, size_t N>
class MyClass
{
public:
template <typename... Args>
void foo(Args&&... args)
{
static_assert(sizeof...(Args) == N, "Wrong number of arguments.");
// Rest of the implementation.
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With