2012-09-18 9 views
7

Poniższy kod wygląda dobrze do mnie:C2070 - nielegalne sizeof operand

#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; 
    } 

Ale kiedy mogę skompilować z VC9 otrzymuję następujący błąd

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

Spodziewam się ten kod do kompilacji. Czy coś mi brakuje? Czy ktoś wie sposób naprawić to dziwne zachowanie (należy pamiętać, że dokładnie to samo bez szablonu kompiluje dobrze i wyjścia 3).

Zauważ, że usunięcie szablonu nie jest opcją, zrobiłem ten przykład, aby odtworzyć problem, który mam w kodzie, gdzie potrzebuję typu zawierającego tablicę jako szablon.

Dzięki

+1

FWIW, Kompiluje dobrze na GCC 4.7.1: http://liveworkspace.org/code/19f48dbdb07463b08a310c168ab59a67. Zobacz, czy to kolejny błąd MSVC czy coś takiego. – chris

+0

Nie sądzę, że wyrażenie oblicza to, co według Ciebie oblicza. – Nobody

+4

@ Nikt 'tablica sizeof/tablica sizeof [0]' jest pospolitym idiomem, który oblicza długość tablicy.Jak myślisz, co on oblicza lub jak sądzisz, co myślą inni ludzie? – hvd

Odpowiedz

4

Jest dobrze zdefiniowane. Należy zauważyć, że w definicji klasy zadeklarowano typ m_kA z typem float[], który jest niekompletnym typem i nie można go używać w połączeniu z sizeof. W definicji m_kA jest ponownie zadeklarowany, aby mieć typ float[3], po czym można używać sizeof. (8.3.4 reguluje znaczenie zgłoszeń tablicy).

Z 3.4.6 Stosując dyrektyw i aliasy namespace [basic.lookup.udir]:

10. Po wszystkich zmian rodzajów (w którym typedef (7.1.3) są zastępowane ich definicjami), typy określone przez wszystkie deklaracje odnoszące się do danej zmiennej lub funkcji muszą być identyczne, z wyjątkiem tego, że deklaracje dla obiektu tablicy mogą określać typy tablic różniące się obecnością lub nieobecnością związane z tablicą (8.3.4). Naruszenie tej zasady w odniesieniu do tożsamości typu nie wymaga diagnozy.

Z 3.9.2 rodzaju związku [basic.compound]:

6 [...] Deklarowany typ obiektu tablicy może być tablicą o nieznanej wielkości i dlatego może być niekompletna w jednym wskaż jednostkę tłumaczeniową i ukończ ją później; typy tablicowe w tych dwóch punktach ("tablica nieznanego ograniczenia T" i "tablica N T") są różnymi typami. [...]

Rozwiązaniem twoich problemów kompilatora byłoby zadeklarować m_kA kompletną typu wprost. Pomocny może też być inny statyczny członek posiadający rozmiar.

[Cytuję z C++ 11, ale zgodnie z moją najlepszą wiedzą C++ 03 działa według tych samych zasad. ]

+1

Byłbym bardzo szczęśliwy, gdyby zainicjowałem inicjalizator, jeśli C++ pozwoliło mi to zrobić. Problem polega na tym, że o ile wiem, mogę to zrobić tylko dla zmiennych lokalnych lub globalnych i jako taki nie jestem w stanie stworzyć dla niego szablonu. Również, jak powiedziałem wcześniej, trudno jest usprawiedliwić VC9 w tym, ponieważ jeśli tylko usunę szablon, wszystko działa. – valerio

+1

Myśląc trochę więcej, konstrukcje takie jak [to] (http://pastebin.com/tumC3NBU) (uwaga: nieważne C++) są uzasadnionym powodem, dla którego typ * powinien * może pozostać 'float []' zamiast 'float [3] 'z szablonami. Ale jak widzieliśmy w usuniętej dyskusji, typem naprawdę jest 'float [3]'. – hvd