2016-03-09 9 views
15

W brzękiem/llvm 3.6.2 następujące wyniki w kod błędu kompilacji podczas kompilacji z std=c++11: liniaCzy jest to niedozwolone pobranie nieregularnego elementu struct struct 'sizeof` w szablonie klasy?

template <typename T=void> 
class bar 
{ 
public: 
    struct foo 
    { 
     int array[10]; 
    }; 

    int baz() 
    { 
     return sizeof(foo::array); 
    } 
}; 

int main(void) 
{ 
    bar<> b; 
    return b.baz(); 
} 

poleceń inwokacja:

$ clang++ -std=c++11 nonstatic.cpp -o nonstatic 
nonstatic.cpp:12:28: error: invalid use of non-static data member 'array' 
     return sizeof(foo::array); 
         ~~~~~^~~~~ 
nonstatic.cpp:20:14: note: in instantiation of member function 
'bar<void>::baz' requested here 
    return b.baz(); 

Gdybym nie zmieni bar być szablon, jak w

class bar 
{ 
public: 
    struct foo 
    { 
     int array[10]; 
    }; 

    int baz() 
    { 
     return sizeof(foo::array); 
    } 
}; 

int main(void) 
{ 
    bar b; 
    return b.baz(); 
} 

wtedy kod kompiluje się czysto. Uwaga: GCC 5.2.1 akceptuje obie wersje pod numerem std=c++11. Warto również zauważyć, że przeniesienie array do szablonu szablonu klasy otaczającej (ale pozostawiając go jako szablonu) powoduje również, że klang to akceptuje.

Jakie zachowanie jest prawidłowe w stosunku do normy? Czy jest to błąd w GCC, klangu lub obu?

(Pytałem tego samego question o użytkowników cfe, ale jak dotąd nie otrzymałem żadnej odpowiedzi).

+1

Wygląda jak błąd w klangu ++. Czekający guru, aby to potwierdzić. – YSC

+2

Tak, na pewno błąd. – SergeyA

+3

Rozwiązania problemu 'sizeof (((foo *) 0) -> array)' wymienione w http://stackoverflow.com/questions/29359661/clang-error-invalid-use-of-non-static-data-member dotyczy tu też. –

Odpowiedz

7

Jest to z pewnością błąd klang; operand twojego wyrażenia sizeof jest id-expression oznaczający niestatyczny element danych, więc [expr.prim.general]/13 posiada. Oto zmniejszona przykład:

template<class T> struct M { int f() { return sizeof(T::x); } }; 
struct S { int x; }; 
int main() { return M<S>{}.f(); } 

Eksponaty błędów przy utrzymaniu członek typu jest dostępne w unevaluated kontekście ramach metody instancji szablonu. Implementacja Clanga n2253 rule enabling the use of non-static data members in unevaluated context (i późniejsze ulepszenia) wydaje się dość krucha i źle współpracuje z szablonami; podobny (choć odrębny) błąd to http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20151019/141535.html.

Nie mogę znaleźć żadnego wskazania, że ​​zostało to już zgłoszone Clang Bugzilla; możesz chcieć otworzyć nowy błąd.

W zależności od sytuacji, obejścia mogą obejmować przenoszenie statycznego typu i obliczeń wartości poza metodą instancji; w szczególności funkcja baz jest wystarczająca, aby przekonać klang do zaakceptowania twojego kodu.

+0

Dzięki za odpowiedź. Pójdę do przodu i zgłoś błąd w bugzilli Clang. Mój przypadek użycia ma długość tablicy jako (prosta) funkcja jednego z parametrów szablonu, więc bardzo łatwo jest użyć tego zamiast wywoływania 'sizeof'. –

+2

Błąd w klangach: https://llvm.org/bugs/show_bug.cgi?id=26893 –

+1

Błąd został naprawiony: https://github.com/llvm-mirror/clang/commit/e4193c5ff01b3e3ef48a2c501e07eaa88683f885 –