2017-02-21 4 views
3

Ich habe Probleme beim Überladen von Operator ==, verschiedene Compilerfehler mit VC++ (2015) und g ++ 5.4.0 (--std == C++ 14). Hier ist der Code (dies ist nur ein Auszug aus einer komplexeren Situation in meiner realen Code-Basis):Probleme beim Überladen von Operator == der Vorlage Sub-Klasse

#include <vector> 

template<typename T> 
struct A { 
    struct B { 
     std::vector<T> _elements; 

     // Internal cmp op. 
     bool operator==(const B &other) { 
      return _elements == other._elements; 
     } 
    }; 

    std::vector<B> _entries; 
}; 

// External cmp op. 
template<typename T> 
inline bool operator==(typename const A<T>::B &l, typename const A<T>::B & r) { 
    return l._elements == r._elements; 
} 

int main() { 
    A<int>::B b0, b1; 

    b0.operator==(b1);       // a 
    operator==<int>(b0, b1);      // b 
    b0 == b1;          // c 

    std::vector<A<int>::B> v0, v1; 

    std::equal(v0.begin(), v0.end(), v1.begin()); // d 
    v0 == v1;          // e 

    return 0; 
} 

ich nicht die Fehlermeldungen hinzufügen, weil ich die Deutsch-Version von VC habe ++ und die g ++ Fehler Spannweite über viele Zeilen.

VC++ gibt einen Fehler an (e). Ich verstehe nicht warum, denn Vektor <> :: operator == scheint std :: equally intern aufzurufen und (d) kompiliert fein. Warum scheitert das?

g ++ akzeptiert meinen externen Operator ==() nicht, so kompiliert vollständig diesen kurzen Code nicht. Ich habe keine Ahnung, wie man einen externen Operator ==() für A <T> :: B schreibt, der mit beiden Compilern funktioniert.

Ich habe noch nicht geklingelt.

Vielen Dank.

+0

"Ich habe die deutsche Version von VC++ und die g ++ Fehler erstrecken sich über viele Zeilen." Englische sind normalerweise nicht so viel besser. – user4581301

Antwort

3

Es waren zwei Fehler in Ihrem Programm:

// Internal cmp op. 
    bool operator==(const B &other) const { 
            ///// <- here 
     return _elements == other._elements; 
    } 

sollte ein const Mitglied sein und das Schlüsselwort const nicht nur hinter dem typename erscheinen:

// External cmp op. 
template<typename T> 
inline bool operator==(typename A<T>::B const& lhs, typename A<T>::B const& rhs) 
             ///// <-   here -> //// 
{ 
    return lhs._elements == rhs._elements; 
} 

Live Example

Beachten Sie, dass die Platzierung von const ist in C++ in der Regel ziemlich liberal, z Sie können sowohl const typename A<T>::B & lhs als auch typename A<T>::B const& lhs schreiben, aber das von Ihnen gewählte Formular typename const A<T>::B & lhs ist nicht zulässig.

Beachten Sie auch, dass Sie entweder ein Mitglied operator== oder ein Nichtmitglied operator== schreiben möchten, aber niemals beide. In Ihrem Fall, weil Tis not deducible in typename A<T>::B, müssen Sie die hässliche operator==<int>(b0, b1) schreiben, um das Nichtmitglied auszuwählen.

Ich würde die Nicht-Mitglied Vorlage operator== entfernen und Ihre Klassenvorlage A<T> ein Nicht-Mitglied

bool operator==(const A &other) const { 
    return _entries == other._entries;  
} 

so hinzufügen, dass Sie auch Objekte von A<int> vergleichen können. Beachten Sie, dass dies die Standardbibliothek operator== für std::vector aufruft, die wiederum Ihren operator== für B aufrufen wird.

+0

Vielen Dank, das hilft bei beiden Problemen. Die const für die Member-Version war nur etwas, was ich im extrahierten Code vergessen habe. Aber ich hätte nie gedacht, dass ein falsch platziertes const so viele verschiedene Fehler erzeugen kann. Die g ++ Fehlermeldungen erwähnen etwas über const, aber ich habe es nicht verstanden. Jetzt ist es etwas klarer und ich muss das im Detail verstehen, nochmals vielen Dank. –

+1

@ Hob-B1T Sie sind willkommen, wenn Sie diese Antwort OK finden, verwenden Sie bitte die Schaltfläche "akzeptieren" – TemplateRex

+0

Der dritte Fehler ist, dass diese Operator-Vorlage nie verwendet wird. –