Pergunta

Eu estou trabalhando em duas classes de mensagens publicitárias que definem tipos de dados reais e complexos. Cada define classe sobrecarregado construtores, bem como os quatro operadores aritméticos +, -, *, / e cinco operadores de atribuição =, + = etc. Para evitar código repetindo, eu estava pensando em usar funções quando o esquerdo e direito modelo -hand-secundários argumentos de um operador são de um tipo de dados diferente:

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

  ...
};

O problema aqui é que o código como:

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

retorna o compilador ( gcc ) erro sobrecarga ambígua para 'operador *' em 'ac * br' , como o compilador não pode dizer a diferença entre:

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

Existe uma maneira para especificar que T não pode ser um complexo no operador de template * definição na classe Real? Ou eu tenho que fazer sem modelos e definir cada operador para cada combinação possível de tipos de dados argumento? Ou há uma maneira de reformular o código?

Foi útil?

Solução

Ah, o problema dos operadores ...

Aumento criou uma biblioteca agradável para que, fornecendo um mínimo de lógica todas as outras variações são automagicamente adicionado para você!

Dê uma olhada Boost.Operators !

Agora, para o seu problema, na verdade, como você percebeu, você terá que definir ambos os sabores dos operadores (int e duplas) ao invés de usar um modelo genérico. Se houver um monte de lógica nestas operadores (o que duvido), você sempre pode tê-los chamar um método comum (templated).

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

Mas se você usar Boost.operators só fornecer Complexo :: operator * = (int) e Complexo :: operator * = (double) e as versões autônomas será automaticamente deduzido:)

(1) Você pode usar passagem por valor aqui, se todos os argumentos são construídos-ins. Você também pode querer considerar Boost.CallTraits , que escolhe automaticamente entre por valor e por-ref dependendo se o argumento é built-in ou não. É útil para modelos.

(2) Ao retornar argumentos por valor, é não-sensical para qualificá-los como const. A palavra-chave const só significa algo para referências e ponteiros, aqui, evita que nada o usuário instanciar um Complex 'simples' ... e você está feliz que não!

Outras dicas

Você poderia fazer tanto o real ou classe Complex tem operadores de multiplicação não globais.

class Real 
{
  ........

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

};

Você pode fazer construtores complexos explícita? Isto significa que a conversão implícita de real de Complexo não é permitido e deve disambiguate o operador *

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top