Domanda

Sto lavorando a due classi wrapper che definiscono tipi di dati reali e complessi. Ogni classe definisce costruttori sovraccaricati, così come i quattro operatori aritmetici +, -, *, / e cinque operatori di assegnazione =, + = ecc. Al fine di evitare la ripetizione del codice, stavo pensando di usare le funzioni del modello quando il lato destro e sinistro gli argomenti lato operatore di un operatore sono di un diverso tipo di dati:

// 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

  ...
};

Il problema qui è quel codice come:

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

restituisce l'errore del compilatore ( gcc ) sovraccarico ambiguo per "operatore *" in "ac * br" , poiché il compilatore non può distinguere tra:

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

C'è un modo per specificare che T non può essere un Complesso nella definizione dell'operatore modello * nella classe Reale? O devo fare a meno dei modelli e definire ciascun operatore per ogni possibile combinazione di tipi di dati argomento? O c'è un modo per ridisegnare il codice?

È stato utile?

Soluzione

Ah, il problema degli operatori ...

Boost ha creato una bella libreria in modo che, fornendo un minimo di logica, tutte le altre varianti vengano automaticamente aggiunte per te!

Dai un'occhiata a Boost.Operators !

Ora per il tuo problema, in realtà come hai notato, dovrai definire entrambe le versioni degli operatori (int e double) anziché utilizzare un modello generico. Se c'è molta logica in questi operatori (di cui dubito), puoi sempre farli chiamare un metodo comune (basato su modelli).

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);
}

Ma se usi Boost.operators fornisci solo Complex :: operator * = (int) e Complex :: operator * = (double) e le versioni autonome verranno automaticamente dedotte :)

(1) In questo caso è possibile utilizzare pass by-value, se tutti gli argomenti sono incorporati. Potresti anche prendere in considerazione Boost.CallTraits , che sceglie automaticamente tra by-value e by-ref a seconda che l'argomento sia incorporato o meno. È utile per i modelli.

(2) Quando si restituiscono argomenti per valore, non è sensato qualificarli come const. La parola chiave Complex significa solo qualcosa per riferimenti e puntatori, qui nulla impedisce all'utente di creare un'istanza di un "semplice" <=> ... e sei fortunato non farlo!

Altri suggerimenti

Puoi fare in modo che la classe Real o Complex abbia operatori di moltiplicazione non globali.

class Real 
{
  ........

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

};

Puoi rendere espliciti i costruttori complessi? Ciò significa che la conversione implicita da reale a complesso non è consentita e dovrebbe chiarire l'operatore *

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top