2017-08-25 2 views
3

Ich habe folgendes:C++: Explizit nennen destructor von typedef Template-Parameter

template <typename X> struct A { 
    typedef X _X; 
}; 

template <typename Y> struct B { // Y is struct A 
    typename Y::_X x; 
    void call_destructor() { 
     x.~Y::_X(); // This doesn't work 
     x.Y::~_X(); // This as well 
    } 
}; 

, die nicht kompiliert und sagte, dass

qualifizierte Typ nicht Destruktornamen überein

Mit dem Schlüsselwort typename vor dem Anruf funktioniert auch nicht. Allerdings ist die folgende kompilieren:

template <typename Y> struct B { 
    typename Y::_X x; 
    typedef typename Y::_X __X; 
    void call_destructor() { 
     x.~__X(); // This works 
    } 
}; 

Kann mir jemand erklären, warum, und ist es eine Möglichkeit, ohne typedef auszukommen?

Antwort

2
x.~Y::_X(); // This doesn't work 

Ist ein Syntaxfehler, glaube ich, der Compiler parst als Aufruf _X in

Der Grund der Das zweite ist ein wenig interessanter.

Wenn Sie eine destructor mit Qualifier nennen (::), wird der Name aus dem Rahmen, wo der vorhergehenden Qualifier wohnt, nachgeschlagen, die den Namen _X im Rahmen nachschlägt

x.Y::~_X(); 

bedeutet wo sich Y befindet, was in diesem Fall der globale Gültigkeitsbereich ist. Da im globalen Bereich kein _X vorhanden ist, schlägt die Suche fehl.

x.Y::_X::~_X(); 

sieht die zweite _X im Bereich, wo der erste _X in residiert, die den Umfang der Y ist, und findet daher das Recht destructor.

Der einfachste Weg, zu schreiben und vergessen die Destruktoraufrufs ist einfach

x.~decltype(x)(); 

aber gcc und msvc versagt diese zu kompilieren.

† Genauer gesagt, ein pseudo-Destruktoraufrufs

4

Sie sollten die destructor anders nennen mit

x.Y::_X::~_X() 

Die folgende Kompilierung gut für mich:

template <typename X> struct A { 
    typedef X _X; 
}; 

template <typename Y> struct B { // Y is struct A 
    typename Y::_X x; 
    void call_destructor() { 
     x.Y::_X::~_X(); // This as well 
    } 
}; 


int main(){ 
    B<A<int> > b; 
    b.call_destructor(); 
} 
+0

Das Komische ist, dass dies allerdings nicht auf Clang funktioniert. Ich frage mich, ob das ein Käfer ist oder ob es eine obskure Regel gibt, warum es schlecht geformt ist. – Brian

+0

Tatsächlich habe ich es erst mit gcc probiert. Das ist ein Rätsel für mich. – Flynsee