2011-01-01 19 views
10

El título es bastante auto-explicativo, pero aquí es un ejemplo simplificado:¿Podemos tener una estructura anónima como argumento de plantilla?

#include <cstdio> 

template <typename T> 
struct MyTemplate { 

    T member; 

    void printMemberSize() { 
     printf("%i\n", sizeof(T)); 
    } 

}; 

int main() { 

    MyTemplate<struct { int a; int b; }> t; // <-- compiler doesn't like this 

    t.printMemberSize(); 

    return 0; 

} 

El compilador se queja cuando trato de usar una estructura anónima como un argumento de plantilla. ¿Cuál es la mejor manera de lograr algo como esto sin tener que tener una definición de estructura separada y nombrada?

Respuesta

7

No se le permite a definir un tipo no identificado como un argumento de plantilla en C++ 03 o incluso en C++ 0x.

Lo mejor que puede hacer es crear una estructura llamada local principal (en C++ 0x)

1: No se les permite usar un tipo local, como parámetro de plantilla en C + +03, sin embargo, C++ 0x lo permite.

Consulte también el Informe de defectos here. La solución propuesta menciona

Los siguientes tipos no deberán utilizarse como una plantilla-argumento para un tipo-parámetro de plantilla:

  • un tipo cuyo nombre tiene ninguna vinculación
  • una clase sin nombre o tipo de enumeración que no tiene nombre para fines de vinculación (7.1.3 [dcl.typedef])
  • una versión cv-calificado de uno de los tipos en esta lista
  • un tipo creado por la aplicación de los operadores declarador a uno de los tipos en esta lista
  • un tipo de función que utiliza una de las tipos de esta lista

El compilador se queja cuando trato de usar una estructura anónimo como un parámetro de plantilla.

¿Quisces decir template argument? El parámetro de la plantilla es diferente del argumento de la plantilla.

Por ejemplo

template < typename T > // T is template parameter 
class demo {}; 

int main() 
{ 
    demo <int> x; // int is template argument 
} 
+0

En C++ 0x, un objeto de un tipo sin nombre se puede deducir como un argumento de plantilla, pero no creo un tipo sin nombre se puede especificar explícitamente en la lista de argumentos de la plantilla. –

+0

Prasoon, ¿me puede remitir a la sección correcta de la norma, por favor? Mi caso de prueba con una estructura sin nombre (pasado a typedef, pero todos sabemos que un nombre typedef no es un nombre de estructura) compila muy bien. –

+0

@Ben: '14.3.1/2' –

4

Su problema no es que la estructura no tenga nombre, sino que la estructura se declara localmente. El uso de tipos locales como argumentos de plantilla no está permitido en C++ 03. Sin embargo, estará en C++ 0x, por lo que puede intentar actualizar su compilador.

EDITAR: En realidad, su problema es que dentro de una lista de argumentos de plantilla no es un lugar legal para poner una definición de clase, con o sin un nombre, de acuerdo con el estándar de C++.

litb señala que a pesar de que encaja en la gramática de C++ 0x, la definición de un tipo que aquí está prohibido por [dcl.type]:

A fi cador-ss tipo específico no deberá de fi nir una clase o enumeración no ser que aparezca en el id. de tipo de una declaración de alias (7.1.3) que no es la declaración de una declaración de plantilla.

simple-template-id: 
    template-name < template-argument-list_opt > 

template-argument-list: 
    template-argument ..._opt 
    template-argument-list , template-argument ..._opt 

template-argument: 
    constant-expression 
    type-id 
    id-expression 

type-id: 
    type-specifier-seq abstract-declarator_opt 

type-specifier-seq: 
    type-specifier attribute-specifier-seq_opt 
    type-specifier type-specifier-seq 

type-specifier: 
    trailing-type-specifier 
    class-specifier 
    enum-specifier 

class-specifier: 
    class-head { member-specification_opt } 

Durante un tiempo tuve una pregunta sobre typedef nombres, pero litb aclarado eso. Que pueden utilizarse como argumentos de plantilla a través de:

trailing-type-specifier: 
    simple-type-specifier 
    elaborated-type-specifier 
    typename-specifier 
    cv-qualifier 

simple-type-specifier: 
    :: opt nested-name-specifier_opt type-name 
    :: opt nested-name-specifier template simple-template-id 
    char 
    char16_t 
    char32_t 
    wchar_t 
    bool 
    short 
    int 
    long 
    signed 
    unsigned 
    float 
    double 
    void 
    auto 
    decltype-specifier 

type-name: 
    class-name 
    enum-name 
    typedef-name 
    simple-template-id 
+0

En realidad estoy usando GCC 4.5 C++ 0x capacidades. ¿Esta característica no se ha implementado allí todavía? – nonoitall

+0

@nonoitall: La [wiki de etiquetas C++ 0x] (http://stackoverflow.com/tags/c%2b%2b0x/info) tiene enlaces a mucha información sobre el estado del soporte de C++ 0x en varios compiladores . Dice que se supone que se debe agregar en gcc 4.5. Las [notas oficiales de la versión de gcc] (http://gcc.gnu.org/gcc-4.5/changes.html) dicen "En modo C++ 0x las clases locales y anónimas ahora están permitidas como argumentos de plantilla". Está compilando con la opción '-std = gnu ++ 0x', ¿verdad? –

+0

Mi mal. Evidentemente, esto es algo que quedó atrás en el puerto MinGW de GCC 4.5. Intenté compilarlo en un cuadro de Linux y se compilará cuando se use una estructura definida localmente (aunque el uso de una estructura anónima como argumento todavía no funcionará)./yo voy a instalar Cygwin. – nonoitall

Cuestiones relacionadas