2012-09-18 18 views
7

El siguiente código se ve bien para mí:C2070 - operando sizeof ilegal

#include <stdio.h> 

    template <typename T> 
    struct A 
    { 
     static float m_kA[]; 
    }; 

    template <typename T> 
    float A<T>::m_kA[] = {1.0f, 2.0f, 3.0f}; 

    int main() 
    { 
     printf("%d\n", 
      sizeof(A<unsigned int>::m_kA)/
      sizeof(A<unsigned int>::m_kA[0])); 
     return 0; 
    } 

Pero cuando compilo con VC9 me sale el siguiente error

error C2070: 'float []': illegal sizeof operand 

yo esperaría este código para compilar. ¿Me estoy perdiendo de algo? ¿Alguien sabe una manera de solucionar este comportamiento extraño (tenga en cuenta que exactamente lo mismo sin la plantilla compila bien y saca 3).

Tenga en cuenta que eliminar la plantilla no es una opción, hice este ejemplo para reproducir un problema que tengo en un código donde necesito que el tipo que contiene la matriz sea una plantilla.

Gracias

+1

FWIW, compila bien en GCC 4.7.1: http://liveworkspace.org/code/19f48dbdb07463b08a310c168ab59a67. Mira que sea otro error de MSVC o algo así. – chris

+0

No creo que la expresión esté calculando lo que crees que está calculando. – Nobody

+4

@ Nadie 'sizeof array/sizeof array [0]' es una expresión común que calcula la longitud de la matriz.¿Qué crees que calcula, o qué crees que otras personas piensan que calcula? – hvd

Respuesta

4

Es bien definido. Tenga en cuenta que en la definición de clase, m_kA se declara con el tipo float[], que es un tipo incompleto y no se puede usar en tándem con sizeof. En la definición de m_kA, se vuelve a declarar que tiene el tipo float[3], después de lo cual está bien usar sizeof. (8.3.4 gobierna el significado de las declaraciones de matriz.)

De 3.4.6 Uso de la Directiva de y alias de espacio de nombres [basic.lookup.udir]:

10 Después de todos los ajustes de tipos (durante el cual typedefs (7.1.3) son reemplazados por sus definiciones), los tipos especificados por todas las declaraciones referentes a una variable o función dada serán idénticos, excepto que las declaraciones para un objeto de matriz pueden especificar tipos de matriz que difieren por la presencia o ausencia de una conjunto de matrices (8.3.4). Una violación de esta regla sobre la identidad de tipo no requiere un diagnóstico.

De 3.9.2 tipos compuesto [basic.compound]:

6 [...] El tipo declarado de un objeto de matriz puede ser una matriz de tamaño desconocido y por lo tanto ser incompleta en uno señalar en una unidad de traducción y completarlo más tarde; los tipos de matriz en esos dos puntos ("matriz de límite desconocido de T" y "matriz de N T") son tipos diferentes. [...]

Una solución para sus problemas de compilador sería declarar m_kA con un tipo de plano completo. Otro miembro estático con el tamaño podría ser útil también.

[Cito de C++ 11 pero a mi leal saber y entender C++ 03 siguió las mismas reglas. ]

+1

Estaría encantado de alinear el inicializador, si C++ me lo permitiera. El problema es que, por lo que sé, solo puedo hacer eso para variables locales o globales, y como tal, no puedo hacer una plantilla para ello. Además, como dije antes, me resulta difícil justificar VC9 en este sentido, porque si solo elimino la plantilla todo funciona. – valerio

+1

Pensando un poco más, las construcciones como [esto] (http://pastebin.com/tumC3NBU) (nota: C++ no válido) son una razón legítima por la que el tipo * debería * quizás seguir siendo 'float []' en lugar de 'float [3] 'con plantillas. Pero como hemos visto en la discusión ahora eliminada, el tipo realmente es 'float [3]'. – hvd