2009-10-27 3 views
2

Я работаю над двумя классами-оболочками, которые определяют реальные и сложные типы данных. Каждый класс определяет перегруженные конструкторы, а также четыре арифметических оператора +, -, *,/и пять операторов присваивания =, + = и т. Д. Чтобы избежать повторения кода, я думал об использовании функций шаблона, когда левое и правое -hand-боковые аргументы оператора имеют другой тип данных:Неоднозначная перегрузка операторов шаблонов

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

    ... 
}; 

проблема здесь состоит в том, что подобный код:

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

возвращает компилятор (НКУ) ошибка неоднозначным перегрузки 'оператор *' in 'ac * ш», так как компилятор не может отличить:

  • template <class T> friend const Complex operator*(const Complex&, const T&)[с T = Real]
  • template <class T> friend const Real operator*(const T&, cont Real&)[с T = Комплексно]

есть способ указать, что T не может быть комплексом в операторе шаблона * определение в классе Real? Или мне нужно обойтись без шаблонов и определить каждый оператор для каждой возможной комбинации типов данных аргументов? Или есть способ перепроектировать код?

ответ

2

Ах, проблемы операторов ...

подталкивания создал хорошую библиотеку, так что, предоставляя минимум логика все остальные варианты автоматически добавляются для вас!

Посмотрите на Boost.Operators!

Теперь для вашей проблемы, как вы заметили, вам придется определять оба варианта операторов (int и double), а не использовать общий шаблон. Если в этих операторах много логики (что я сомневаюсь), вы всегда можете вызвать их общий (шаблонный) метод.

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

Но если вы используете Boost.operators вы предъявите Complex :: оператор * = (INT) и Complex :: оператор * = (дважды) и автономные версии будут автоматически выведены :)

(1) Здесь вы можете использовать pass by-value, если все аргументы являются встроенными. Вы также можете рассмотреть Boost.CallTraits, который автоматически выбирает между значениями и по-ref в зависимости от того, встроен или нет аргумент. Это удобно для шаблонов.

(2) При возврате аргументов по значению, нечувствительно считать их const. Ключевое слово const означает только что-то для ссылок и указателей, здесь ничего не мешает пользователю создать экземпляр «простой» Complex ...и вам повезло, что нет!

1

Вы можете сделать, чтобы класс Real или Complex имел неглобальные операторы умножения.

class Real 
{ 
    ........ 

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

}; 
0

Можете ли вы сделать сложные конструкторы ясными? Это будет означать, что неявное преобразование из Real в комплекс не допускается и должна неоднозначностью оператора *

+0

Конструкторы должны быть сделаны явно (вопрос отредактирован). Однако в этом случае их явное не устраняет ошибку компиляции. – ASV