2010-11-28 26 views
6

El siguiente código de ejemplo se compila bajo gcc y funciona como esperaría. Me permite crear una instancia de un objeto con una definición de función como parámetro de plantilla, pero luego la clase puede usar los diferentes tipos en la función como si se pasaran individualmente como parámetros de plantilla de tipo.Conversión del parámetro de plantilla no tipo de puntero de función a tipo Parámetros de plantilla

template<class FuncSignature> class Obj; 

template<class Type1, class Type2> class Obj<Type1 (Type2)> 
{ 
public: 
    Type1 var1; 
    Type2 var2; 
}; 

int main(int argc, char **argv) 
{ 
    Obj<char (int)> A; 
    A.var1 = 'a'; 
    A.var2 = 3; 
} 

A pesar de que parece que funciona, no estoy seguro de lo que este código está haciendo. ¿Por qué funciona este código y cumple con el estándar de C++?

+1

sí, es legal, cuando no estoy seguro, pruebo http://www.comeaucomputing.com/tryitout/ para verificar el cumplimiento. funciona debido a la especialización de plantilla parcial. – Anycorn

+0

Con metaprogramación, puede extraer la mayoría de la información sobre un tipo de función (aquí 'char (int)') usando la biblioteca Boost FunctionTypes: http://www.boost.org/doc/libs/1_45_0/libs/function_types/ doc/html/index.html Podría ser un código duro, pero es una lectura interesante :) –

Respuesta

7

¿Por qué no debería funcionar? La creación de instancias coincide con la especialización, que extrae los tipos de componente (char y int) del tipo compuesto (una función, char(int)) como Type1 y Type2.

Por cierto, no tiene un parámetro de plantilla sin tipo. Un tipo de función es un tipo. Si usted tenía un parámetro de plantilla no tipo, entonces se vería así:

template <char(int)> 
struct X {}; 

char foobar(int); 

int main() 
{ 
    X<foobar> x; 
} 

o totalmente con plantilla:

template <class R, class A, R(A)> 
//       ^^^^ 
//      non-type parameter 
struct X {}; 

char foobar(int); 

int main() 
{ 
    X<char, int, foobar> x; 
//    ^^^^^^ 
// a specific function, not type 
} 
+2

Percibo la fuente de confusión aquí: "Una función es un tipo". eso no es realmente cierto Solo si sabes estas cosas, puedes deducir lo que significa esta oración. Para reducir la fuente de confusión, mejor decir con precisión "Un tipo de función es un tipo". Del mismo modo, un entero no es un tipo. Pero un tipo entero es. De la misma manera, el que pregunta probablemente se confundió diciendo "me permite crear una instancia de un objeto con una definición de función como un parámetro de plantilla" - esa afirmación no tiene sentido de ninguna manera. –

+0

@Johannes: observado. – UncleBens

+0

Veo que estaba confundido de muchas maneras. Un ser que no sabía char (int) era un tipo conocido como tipo de función. Tampoco me di cuenta de que se estaba produciendo una especialización de plantilla basada en este tipo de función. Nunca he visto una especialización de plantilla que tenga una lista de plantillas no vacía. ¿Hay casos distintos a los que se especializan en un tipo de función donde eso puede suceder? – user334066

3

Esta pregunta es incorrecta porque FuncSignature no es un parámetro de plantilla sin tipo.

Sin embargo, el código funciona dada por la especializada (general) y el tipo FuncSignature para este tipo de función unarios (Type1 (Type2) es un tipo de función, teniendo en cuenta los tipos y Type1Type2).

Así que la primera línea define una plantilla general, el siguiente grupo de líneas se especializa por la forma de tipo Type1 (Type2), que son parametrizado en dos tipos, de ahí la especialización tiene una lista de parámetros de plantilla no vacío, y el main crea una instancia del plantilla para el tipo concreto char (int) (una función tomando un int y devolviendo un char).

0

Sí. Este código se ajusta el estándar :)

En el caso de:

Obj<char (int)> 

Type1 es char y Type2 es int. Por ese motivo, Obj::var1 es una variable miembro del tipo char y Obj::var2 es una variable miembro del tipo int.

Cuestiones relacionadas