Überladen des Ausgabeoperators für eine Klassenvorlage in einem Namespace

8

Ich habe dieses Programm

%Vor%

Die Kompilierung schlägt fehl, weil der Compiler keinen Ausgabeoperator für skg :: Triplet finden konnte. Aber der Ausgabeoperator existiert.

Wenn ich Triplet aus dem skg-Namespace in den globalen Namespace verschiebe, funktioniert alles einwandfrei. Was ist hier falsch?

    
Surya 29.01.2010, 03:28
quelle

1 Antwort

13

Sie müssen Ihre Implementierung von operator<< in denselben Namespace wie Ihre Klasse verschieben. Es sucht:

%Vor%

Aber wird es wegen einer Kürzung im argumentabhängigen Look-up (ADL) nicht finden. ADL bedeutet, dass, wenn Sie eine freie Funktion aufrufen, diese Funktion in den Namespaces ihrer Argumente suchen wird. Dies ist der gleiche Grund, warum wir tun können:

%Vor%

Auch wenn operator<<(std::ostream&, const char*) im Namensraum std ist. Für Ihren Aufruf sind diese Namespaces std und skg .

Es wird in beiden nachsehen, nicht in skg (da Ihre im globalen Bereich ist), dann in std . Es wird Möglichkeiten sehen (alle normalen operator<< ), aber keine davon passt. Da der laufende Code (der Code in ostream_iterator ) im Namespace std liegt, ist der Zugriff auf den globalen Namespace komplett weg.

Indem Sie Ihren Operator im selben Namespace platzieren, funktioniert ADL. Dies wird in einem Artikel von Herb Sutter diskutiert: "Ein bescheidener Vorschlag: ADL reparieren. " . (PDF) In der Tat, hier ist ein Ausschnitt aus dem Artikel (zeigt einen Mangel):

%Vor%

Gleiche Situation, die Sie haben.

Das Buch "C ++ Coding Standards" von Sutter und & amp; Alexandrescu hat eine nützliche Richtlinie:

  
  1. Behalten Sie einen Typ und seine Nicht-Member-Funktionsschnittstelle im selben Namespace.
  2.   

Folge ihm und du und ADL werden glücklich sein. Ich empfehle dieses Buch, und selbst wenn du es nicht bekommst, lies wenigstens das PDF, das ich oben verlinkt habe; Es enthält die relevanten Informationen, die Sie benötigen sollten.

Beachten Sie, dass Sie nach dem Verschieben des Operators Ihre Friend-Direktive benötigen (damit Sie auf private Variablen zugreifen können):

%Vor%

Und ta-da! Behoben.

    
GManNickG 29.01.2010, 03:35
quelle