2012-10-06 29 views
7

Encuentro algo molesto en C++ y no sé si hay un truco para evitar esto sin gastos generales. El problema es el siguiente:¿Por qué tenemos que especificar <> para una clase de plantilla con parámetros predeterminados?

Para una función de plantilla, podemos tener:

// Function declaration/definition 
template<bool Option = false> void myFunction() 
{ 
    std::cout<<"Option = "<<Option<<std::endl; 
} 

// Then I can use : 
myFunction<false>(); 
myFunction<true>(); 
myFunction(); // <- NO PROBLEM HERE 

Ahora, para una clase de plantilla:

// Class definition/declaration 
template<bool Option = false> class MyClass 
{ 
}; 

// Then I can use : 
myClass<false> x; 
myClass<true> y; 
myClass z; // <- PROBLEM HERE : only "MyClass<> z;" will compile ! 

¿Por qué es la razón de este comportamiento? ¿Hay algún truco para evitar eso? Para una clase con los parámetros optionnal pasados ​​como plantilla, creo que este no es conveniente para el usuario final: él debe ser capaz de utilizar la implementación predeterminada como una clase de plantilla sin ...

+0

"* ¿Hay algún truco para evitar eso? *" No, a menos que considere crear un nuevo tipo (con un nombre diferente) que herede públicamente de él y reenvía todos los constructores. – ildjarn

+4

O simplemente use un typedef en lugar de herencia: 'typedef myClass myClassDef;' –

+0

@Remy: Oh sí, o eso. :-P Creo que mi cerebro está listo para el día. – ildjarn

Respuesta

8

¿Por qué es la razón de este comportamiento?

Es porque las funciones se pueden sobrecargar y los tipos no.

Cuando se escribe una llamada a la función, el compilador rellena un conjunto de sobrecarga de todas las funciones que puede encontrar con ese nombre y, a continuación, se da cuenta de cuáles coinciden con el argumento (s) pasado. Ahora, para que esto funcione limpiamente con plantillas de funciones, permite que los tipos de argumento de la plantilla se deduzcan de los parámetros. Como la inferencia de parámetros de tipo está permitida en general, funciona para su caso incluso cuando el parámetro está predeterminado.

Los tipos, sin embargo, no están sobrecargados. Mientras que myFunction<true>() y myFunction<false>() están relacionados en la medida en que participen en el mismo conjunto de sobrecarga, myClass<true> y myClass<false> son tipos de no relacionados independientes. Sin un equivalente de sobrecarga en los nombres de tipos, no hay motivación para agregar un caso especial para nombrar implícitamente una clase de plantilla totalmente especializada. Los parámetros nunca se pueden inferir, por lo que equivaldrían a una sintaxis especial solo para el caso en que estén todos predeterminados.

¿Hay algún truco para evitar eso?

En general, si usted quiere conseguir la deducción argumento de plantilla para clases de plantilla, puede proporcionar una envoltura función de plantilla (esto funciona mejor con C++ 11 automático)

template <bool Option=false> class MyClass {}; 
template <bool Option=false> MyClass<Option> make_my_class() { 
    return MyClass<Option>(); 
} 
// ... 
auto z = make_my_class(); 

lo contrario, creo usar typedef (según el comentario de Remy) es la mejor opción.

3

myClass es una plantilla de clase, no una clase. Solo myClass<true>, o myClass<>, es una clase.

De forma similar, myFunction es una plantilla de función, no una función. Sin embargo, cuando está invocando a temp ­ la ­ función ted, los argumentos de la plantilla pueden deducirse por usted, y usted no necesita especificar explícitamente los argumentos de la plantilla si pueden deducirse. Por lo tanto, la expresión de llamada de función myFunction(); es válida, y el primer argumento se deduce como false. Es solo que la deducción ocurre gracias al argumento predeterminado en lugar de coincidir con los argumentos de la función.

Cuestiones relacionadas