2015-03-21 8 views
10

diesen Code vor:Warum dürfen wir die Adresse eines unvollständigen Typs annehmen?

class Addressable; 
class Class1 { void foo(Addressable &a) { (void) &a; } }; // OK 
class Addressable { void *operator &() { return this; } }; 
class Class2 { void foo(Addressable &a) { (void) &a; } }; // Error: operator & private 

Warum C++ unter der Adresse eines unvollständigen Referenztyp erlauben?

Könnte es nicht potenziell illegal sein, wie oben gezeigt? Ist das beabsichtigt?

+4

Ich denke, die bessere Frage ist "Warum erlaubt C++ das Überladen von' & 'an erster Stelle": D –

+0

Ich hatte keine Ahnung, dass Sie 'Operator &()' überladen könnten. Manchmal denke ich, C++ lässt Entwickler zu * zu viel *. – tenfour

+0

@tenfour: Ich kann buchstäblich nur an eine Situation denken, in der es nützlich ist, und das ist, wenn * die Adresse der Operation in Lambda-Notation, z. 'foo [& _ 1]'. – Mehrdad

Antwort

5

Ja, das ist beabsichtigt, und die Möglichkeit eines Bruchs, wenn überlastet ist, ist bekannt.

Die Übernahme der Adresse unvollständiger Typen ist schon lange vor C++ möglich. In C besteht absolut keine Bruchgefahr, da & nicht überlastet werden kann.

C++ entschied sich, die zuvor gültigen Programme nicht unnötig zu unterbrechen, und spezifizierte einfach, dass wenn ein unvollständiger Typ sich als überladener &-Operator herausstellt, es nicht spezifiziert ist, ob der überladene Operator verwendet wird.

Zitiert N4140:

5.3.1 Unäre Operatoren [expr.unary.op]

Wenn & zu einem L-Wert von unvollständigem Klassentyp und dem vollständigen Typ operator&() erklären sie angewandt wird, ist nicht spezifiziert, ob der Operator die eingebaute Bedeutung hat oder die Operatorfunktion aufgerufen wird.

Dies interpretiert werden kann, auch zu einer Klasse gilt zur Zeit, erklärt zu werden und selbst wenn eine Erklärung von operator& bereits gesehen hat:

extern struct A a; 
struct A { 
    int operator&(); 
    decltype(&a) m; // int, or A *? 
}; 
int main() { 
    return A().m; // only valid if m is int 
} 

Hier gibt GCC m Typen A * und das Programm ablehnt , aber Klang gibt es Typ int und akzeptiert es.

+0

+1 wow. Bleibt der letzte Satz bestehen, auch wenn '&' nicht verwendet wird, wenn der Typ unvollständig ist? Mit anderen Worten, kann der Compiler offensichtlich "&" die ganze Zeit überladen ignorieren? – Mehrdad

+0

@Mehrdad Ich verstehe nicht, was Sie mit diesem Kommentar meinen. Wenn der Compiler erkennt, dass der Typ unvollständig ist, dann wird der Versuch, nach einem überladenen "Operator &" zu suchen, fehlschlagen, so dass nur der eingebaute Operator gefunden werden kann. Aber gleichzeitig muss ein Compiler nicht genau verfolgen, an welchen Stellen des Programms der Typ noch nicht vollständig ist. Wenn die Kompilierung nicht streng von oben nach unten erfolgt, kann der Typ als vollständig (und finde den überladenen Operator, auch wenn du es nicht erwartest. – hvd

+0

Ich sage nur, dass dein letzter Satz nicht klar macht, wann genau das Verhalten nicht spezifiziert ist: ist es immer unspezifiziert oder nur unspezifiziert, wenn '&' noch nicht definiert ist? – Mehrdad