Overloading template classes by template parameter

2019-01-17 20:46发布

问题:

Is it possible to have multiple versions of the same class which differ only in the number of template arguments they take?

For instance:

template<typename T>
class Blah {
public:
    void operator()(T);
};

template<typename T, typename T2>
class Blah {
public:
    void operator()(T, T2);
};

I'm trying to model functor type things which can take a variable number of arguments (up to the number of different templates that were written out).

回答1:

The simplest answer would be to have just one template, with the maximum number you want to support and use void for a default type on all but the first type. Then you can use a partial specialization as needed:

template<typename T1, typename T2=void>
struct foo {
    void operator()(T1, T2);
};

template <typename T1>
struct foo<T1, void> {
     void operator()(T1);
};

int main() {
   foo<int> test1;
   foo<int,int> test2;
   test1(0);
   test2(1,1);
}


回答2:

A template can have only one base definition. If you need a variable number of arguments and you don't want to use "null type" constructions as @awoodland suggests, and if you have a C++0x compiler, then you can use variadic templates:

template <typename ...Dummy> struct foo; // base case, never instantiated!

template <typename T> struct foo<T> { /*...*/ };  // partial spec. for one parameter
template <typename T, typename U> struct foo<T, U> { /*...*/ };  // ditto for two


回答3:

This is untested code, I don't have a version of boost handy, but here goes anyway

#include "boost/tuple.h"

template <class T>
class Blah;

template <class T>
class Blah< boost::tuple<T> >
{
  void operator()(T arg);
};

template <class T, class U>
class Blah< boost::tuple<T, U> >
{
  void operator()(T arg1, U arg2);
};

etc. etc.