Frage

Ich arbeite an zwei Wrapper-Klassen, die reale und komplexe Datentypen definieren. Jede Klasse definiert ladenen Konstruktoren sowie die vier arithmetischen Operatoren +, -, *, / und fünf Zuweisungsoperatoren =, + = usw. Um sich wiederholende Code zu vermeiden, dachte ich an Template-Funktionen zu verwenden, wenn die linken und rechten Boerse seitigen Argumente eines Bedieners sind von einem anderen Datentyp:

// real.h
class Real {
public:
  explicit Real(const double& argument) {...}
  explicit Real(int argument) {...}
  ...

  friend const operator*(const Real&; const Real&);
  template <class T> friend const Real operator*(const Real&, const T&);
  template <class T> friend const Real operator*(const T&, cont Real&);
  // Here, T is meant to be a template parameter for double and int

  // Repeat for all other arithmetic and assignment operators
};

// complex.h
class Complex {
public:
  explicit Complex(const Real& realPart) {...}
  explicit Complex(const Real& realPart, const Real& imaginaryPart) {...}
  // Overload for double and int data types
  ...

  friend const operator*(const Complex&, const Complex&);
  template <class T> friend const Complex operator*(const Complex&, const T&);
  template <class T> friend const Complex operator*(const T&, cont Complex&);
  // Here, T is is a template parameter for Real, double and int

  ...
};

Das Problem hierbei ist, dass Code wie:

//main.cpp
void main() {
  Complex ac(2.0, 3.0);
  Real br(2.0);
  Complex cc = ac * br;
}

gibt den Compiler ( gcc ) Fehler mehrdeutig Überlastung für 'operator *' in 'ac * br , da der Compiler nicht den Unterschied zwischen sagen kann:

  • template <class T> friend const Complex operator*(const Complex&, const T&) [mit T = Real]
  • template <class T> friend const Real operator*(const T&, cont Real&) [mit T = Complex]

Gibt es eine Möglichkeit zu geben, dass T nicht ein Komplex in der Vorlage Operator * Definition in der Klasse wirklich sein kann? Oder muss ich ohne Vorlagen zu tun und jeder Betreiber für jede mögliche Kombination von Argument Datentypen definieren? Oder gibt es eine Möglichkeit, den Code neu zu gestalten?

War es hilfreich?

Lösung

Ach, das Problem der Betreiber ...

erstellt-Boost eine schöne Bibliothek, so dass durch ein Minimum an Logik alle anderen Varianten bieten für Sie automatisch hinzugefügt werden!

Hier finden Sie aktuelle Boost.Operators !

Jetzt für dein Problem, tatsächlich, wie Sie bemerkt haben, werden Sie beide Aromen der Operatoren (int und double) definieren müssen, anstatt eine generische Vorlage. Wenn es eine Menge von Logik in diesen Operatoren ist (was ich bezweifle), können Sie immer sie nennen einen gemeinsamen (Templat) -Methode.

template <typename T>
Complex complex_mult_impl(T const& lhs, Complex const& rhs) { ... } // Note (1)

// return type is not 'Complex const', see (2)
Complex operator*(int lhs, Complex const& rhs)
{ 
  return complex_mult_impl(lhs,rhs);
}

Wenn Sie aber Boost.operators verwenden Sie bieten Complex :: operator * = (int) und Complex :: operator * = (double) und die eigenständigen Versionen automatisch abgeleitet werden:)

(1) Sie könnten Pass von-Wert verwenden hier, wenn alle Argumente sind Einbauten. Vielleicht möchten Sie auch prüfen, Boost.CallTraits , welche wählt automatisch zwischen by-Wert und Neben ref abhängig, wenn das Argument eingebaut ist oder nicht. Es ist praktisch für die Vorlagen.

(2) Wenn Argumente von Wert zurückgibt, ist es nicht unsinnig, sie als const zu qualifizieren. Das const Schlüsselwort bedeutet nur etwas für Referenzen und Zeiger, hier nichts den Benutzer verhindert, dass ein ‚einfache‘ Complex zu instanziiert ... und Sie haben das Glück, es funktioniert nicht!

Andere Tipps

Sie könnten machen entweder Real oder Complex Klasse nicht-globale Multiplikationsoperator.

class Real 
{
  ........

  template <class T> const Real operator*(const T&);
  const Real operator*(const Real&);

};

können Sie komplexe Konstrukteurs explizit zu machen? Dies bedeutet, dass die implizite Konvertierung von Real-Komplex ist nicht erlaubt und soll den Betreiber * disambiguate

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top