2011-08-08 5 views
16

¿Es posible tener múltiples versiones de la misma clase que difieran solo en el número de argumentos de plantilla que toman?Sobrecarga de clases de plantilla por número de parámetro de plantilla

Por ejemplo:

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

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

que estoy tratando de modelar tipo funtor cosas que pueden tomar un número variable de argumentos (hasta el número de diferentes plantillas que se escribieron).

+0

me pregunto si podría hacer algo con TypeListas. – john

+0

@john que sería una buena idea, pero estoy usando MSVC++ 2010 que no los admite. No lo creo. –

+0

Realmente boost :: tuple es probablemente una versión más accesible de la misma idea. Tener una plantilla genérica con un tipo, luego una versión especializada con tuplas para dos, tres, cuatro ... tipos. – john

Respuesta

22

La respuesta más simple sería tener solo una plantilla, con el número máximo que desea admitir y usar void para un tipo predeterminado en todos excepto en el primer tipo. A continuación, puede utilizar una especialización parcial, según sea necesario:

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); 
} 
+1

No creo que la definición de 'operator() (T, T2, T3, T4)' funcionaría correctamente si algunos de los tipos fueran 'void'. –

+0

@Ben tienes razón, no es así, ya lo he intentado. –

+2

@ben - No funciona así, de ahí la especialización parcial que efectivamente da la "sobrecarga" en el número de argumentos de la plantilla – Flexo

14

Una plantilla puede tener sólo uno definición de base. Si necesita un número variable de argumentos y no desea utilizar construcciones de tipo "nulo" como @awoodland indica, y si tiene un compilador de C++ 0x, a continuación, puede utilizar plantillas variadic:

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 
0

Este es el código no probado, no tengo una versión de impulso a mano, pero aquí va de todos modos

#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

Cuestiones relacionadas