You don't have to do what you're doing, but it's the most flexible approach. A one-parameter template with specialization goes like this:
A template parametrized on one type...
template <typename> struct Foo;
... but it is only defined for function types:
template <typename R>
struct Foo<R()> { /* ... */ };
template <typename R, typename A1>
struct Foo<R(A1)> { /* ... */ };
template <typename R, typename ...Args>
struct Foo<R(Args...)> { /* ... */ };
The alternative would be to hard-code the signature of the function:
A class template that stores the function pointer of a one-argument function:
template <typename R, typename A>
struct Bar
{
R (*fp)(A);
Bar(R(*f)(A)) : fp(f) { }
// ...
};
As you can see, the first approach is much more general, as we can specialize Foo
for any function type we like. By contrast, the direct template in the second example is intricately tied to the details of the function signature and cannot easily be generalized.
T
andU
if you prefer. That's just not as flexible.