Betrachten Sie eine Legacy-Klassenvorlage mit überladenen Additionsoperatoren +=
und +
Bei der Code-Überprüfung wird beobachtet, dass +
in +=
implementiert werden kann. Warum also nicht ein Nicht-Member (und garantiert Symmetrie für linke und rechte Argumente)?
Es sieht sicher genug aus, weil alle gültigen Ausdrücke, die +
und +=
verwenden, ihre ursprüngliche semantische Bedeutung behalten.
Frage : Kann das Refactoring von operator+
von einer Member-Funktion in eine Nicht-Member-Funktion einen Code unterbrechen?
Definition der Bruchstelle (schlechteste bis beste)
operator+
auf (von der Basisklasse oder dem zugehörigen Namespace, der über ADL gezogen wurde) Die Antwort ist, ja, es wird immer Bruch geben. Der wesentliche Bestandteil ist, dass die Argumentableitung von Funktionsvorlagen keine impliziten Konvertierungen berücksichtigt. Wir betrachten drei Szenarien, die die drei syntaktischen Formen abdecken, die ein überladener Operator annehmen kann.
Hier verwenden wir einen impliziten Konstruktor innerhalb von X<T>
selbst. Aber selbst wenn wir diesen Konstruktor explicit
hätten, könnten Benutzer dem Namensraum X<T>
eine Klasse C<T>
hinzufügen, die eine implizite Konvertierung der Form operator X<T>() const
enthält. Die folgenden Szenarien würden in diesem Fall weiterhin gelten.
Eine Friend-Funktion, die kein Mitglied ist, bricht am wenigsten in dem Sinne, dass sie implizite Konvertierungen von lhs-Argumenten erlaubt, die nicht für die Member-Funktion einer Klassenvorlage kompiliert werden. Die Nicht-Member-Funktionsvorlage bricht die implizite Konvertierung für rhs-Argumente.
Dieser Code erlaubt einen Ausdruck wie
%Vor% Da die Funktion friend
keine Vorlage ist, findet keine Argumentableitung statt, und sowohl das Argument lhs als auch rhs betrachten implizite Konvertierungen
In diesem Fall werden die Argumente lhs und rhs einer Argumentableitung unterzogen und berücksichtigen keine impliziten Konvertierungen:
%Vor%