2016-03-09 5 views
15

In Klirren/llvm 3.6.2 Der folgende Code führt zu einem Kompilierungsfehler, wenn sie mit std=c++11 Kompilieren:Ist es illegal, dass 'sizeof` nicht-statisches Mitglied von struct in der Klassenvorlage verschachtelt wird?

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(); 
} 

Kommandozeilenaufruf:

$ 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(); 

Wenn ich bar ändern ein nicht mehr zu sein, Vorlage, wie in

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

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

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

dann kompiliert der Code sauber. Beachten Sie, dass GCC 5.2.1 beide Versionen unter std=c++11 akzeptiert. Beachten Sie auch, dass das Verschieben von in den umschließenden Klassenschablonenkörper (aber als Vorlage) auch dazu führt, dass dies akzeptiert wird.

Welches Verhalten ist korrekt gegenüber dem Standard? Ist das ein Fehler in GCC, Clam oder beides?

(Ich fragte die gleiche question auf cfe-Benutzer, aber bisher keine Antwort erhalten haben).

+1

Sieht aus wie ein clang ++ Bug. Wartende Gurus bestätigen dies. – YSC

+2

Ja, sicherlich ein Fehler. – SergeyA

+3

Die Problemumgehung 'sizeof (((foo *) 0) -> array)', die in http://stackoverflow.com/questions/29359661/clang-error-invalid-use-of-non-static-data-member erwähnt wird, gilt auch hier. –

Antwort

7

Dies ist sicherlich ein Clang Bug; Der Operand Ihres sizeof Ausdrucks ist ein ID-Ausdruck, der ein nicht statisches Datenelement bezeichnet, also [expr.prim.general]/13 hält. Hier ist ein Beispiel reduziert:

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

Der Fehler zeigt, wenn ein abhängiges Typ Glied in einem nicht ausgewertete Rahmen innerhalb einer Vorlageninstanz Methode zugegriffen wird. Clangs Implementierung der n2253 rule enabling the use of non-static data members in unevaluated context (und späteren Verbesserungen) scheint ziemlich fragil zu sein und schlecht mit Vorlagen zu interagieren; Ein ähnlicher (wenn auch deutlicher) Fehler ist http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20151019/141535.html.

Ich kann keinen Hinweis darauf finden, dass dies bereits gemeldet wurde Clang Bugzilla; Vielleicht möchten Sie einen neuen Fehler öffnen.

Je nach Situation können Problemumgehungen das Verschieben der statischen Typ- und Wertberechnungen außerhalb der Instanzmethode umfassen. Vor allem sogar baz eine static Member-Funktion ist genug, um Clang zu überzeugen, Ihren Code zu akzeptieren.

+0

Danke für die Antwort. Ich werde weitermachen und einen Bug mit dem Clang Bugzilla einreichen. Mein Anwendungsfall hat die Länge des Arrays als (einfache) Funktion eines der Template-Parameter, so dass es für mich sehr einfach ist, das zu verwenden, anstatt "sizeof" aufzurufen. –

+2

Clang Bug eingereicht: https://llvm.org/bugs/show_bug.cgi?id=26893 –

+1

Der Bug wurde behoben: https://github.com/llvm-mirror/clang/commit/e4193c5ff01b3e3ef48a2c501e07eaa88683f885 –

Verwandte Themen