5

folgendes Beispiel:Benutzerdefinierte implizite Umwandlung einer Enum-Klasse, wenn ein überladenen Operator Aufruf fehlschlägt

struct ConvertibleStruct {}; 

enum class ConvertibleEC {}; 

struct Target { 
    // Implicit conversion constructors 
    Target(ConvertibleStruct) {} 
    Target(ConvertibleEC) {} 
}; 

Target operator~(const Target& t) { 
    return t; 
} 

Target anotherFunction(const Target& t) { 
    return t; 
} 

int main() { 
    ConvertibleStruct t; 
    ConvertibleEC ec; 

    ~t;     // 1. Works finding the operator overloaded above 
    ~ec;     // 2. Fails to compile on clang 3.4 and gcc 4.8.2 
    operator~(ec);  // 3. Works finding the operator overloaded above 

    anotherFunction(ec); // 4. Works 
} 

Compiler-Versionen:

Die obigen Ergebnisse sind für clang 3.4 und gcc 4.8.2. Test 2 kompiliert tatsächlich gut unter gcc 4.7.3 mit -std=c++11. Möglicherweise ein Fehler in der frühen GCC C++ 11 Implementierung?

Assertions:

  • Da 1. compiliert, benutzerdefinierte implizite Konvertierungen überprüft werden, wenn die ~ Operator aufrufen.
  • Angesichts 4. Compiles werden benutzerdefinierte implizite Konvertierungen für enum class Objekte überprüft.

Fragen:

  • Sind die oben genannten Behauptungen richtig?
  • Wenn sie sind, warum kompiliert 2. nicht?
  • Gegeben, dass 2. nicht kompiliert, warum kompiliert 3.?

Antwort

4

Der zweite Test, ~ec läuft in eine Eigentümlichkeit der Namenssuche für Operatoren in Ausdrücken: [over.match.oper]/3 (aus dem "alten" N3797):

Für eine unärer Operator @ mit einem Operanden von einem Typ, deren cv-unqualifizierte Version ist T1 [...]

der Satz von Dritt Kandidaten ist das Ergebnis der unqualifizierten lookup von [email protected] im Zusammenhang mit dem Ausdruck gemäß die usua l Regeln für die Namenssuche in unqualifizierten Funktionsaufrufen mit der Ausnahme, dass alle Mitgliedsfunktionen ignoriert werden. Wenn jedoch kein Operand einen Klassentyp hat, werden nur die nicht-Elementfunktionen in der Lookup gesetzt, die einen ersten Parameter vom Typ T1 oder „Referenz auf (möglicherweise cv-qualifiziert) T1“ haben, wenn T1 ist eine Aufzählung Typ [...] sind Kandidatenfunktionen.

Also die ::operator~(const Target&) sollte nicht mit einem für einen Ausdruck mit einem unären Operator angewandt auf einen Operanden vom Typ ConvertibleEC gefunden/verwendet werden.


Zum ersten, ~t ist der Operand von Klassentyp und die obige Ausnahme gilt nicht.

Sowohl der dritte als auch der vierte Test verwenden nicht die Operator-Suche, sondern die übliche unqualifizierte Suche.Die übliche nicht qualifizierte Suche findet ::operator~(const Target&) (in Fällen 1 und 3) und anotherFunction (in Fall 4).

+1

Dies scheint eine Vor-Standardisierung Entscheidung zu sein: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1997/N1137.asc Ich bin mir nicht sicher über die Begründung. – dyp

+0

Interessant. Dies erklärt möglicherweise auch, warum es auf 'gcc 4.7.3' kompiliert. IIRC, die 'enum class' Implementierung in GCC zu dieser Zeit basierte auf' struct's – Clivest