I am working on two wrapper classes that define real and complex data types. Each class defines overloaded constructors, as well as the four arithmetic operators +,-,*,/ and five assignment operators =,+= etc. In order to avoid repeating code, I was thinking of using template functions when the left- and right-hand-side arguments of an operator are of a different data type:
// 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
...
};
The problem here is that code like:
//main.cpp
void main() {
Complex ac(2.0, 3.0);
Real br(2.0);
Complex cc = ac * br;
}
returns the compiler (gcc) error ambiguous overload for 'operator*' in 'ac * br', as the compiler cannot tell the difference between:
template <class T> friend const Complex operator*(const Complex&, const T&)
[with T = Real]template <class T> friend const Real operator*(const T&, cont Real&)
[with T = Complex]
Is there a way to specify that T cannot be a Complex in the template operator* definition in the class Real? Or do I have to do without templates and define each operator for every possible combination of argument data types? Or is there a way to redesign the code?