How to resolve ambiguous operator in ISO C++ - c++

I'm pretty much out of ideas now with porting a big bunch of old C++ code from MS Visual C++ 7.0 to iOS 4 iPhone g++ 4.2.1 compiler. I get some ambiquity errors compiling this:
complex_d* cp;
complex_d qSt;
double zi;
// complex_d += complex_d * double
*cp += qSt * dVal; // ISO C++ says that these are ambiguous
with the class definition of complex_d as:
#include <math.h>
#include "CObject.h" // emulated MFC class, used for some types like BOOL
#include "CString.h" // emulated MFC class, also needed for some types not on iOS
// interface for complex calculations
//
/////////////////////////////////////////////////////////////////////////////
class polar_d; // forward declaration
class complex_d
{
// attributes
protected:
double re;
double im;
// construction
public:
complex_d(double re = 0, double im = 0);
complex_d(const complex_d& x);
virtual ~complex_d() { };
// implementation
public:
double real(void) const;
double imag(void) const;
double& setReal(void); // needed because we don't have Serialize() here
double& setImag(void); // as above
double Abs(void) const;
double Phi(void) const;
complex_d Conjugate(void);
polar_d Polar(void);
BOOL IsZero(void) const;
BOOL IsReal(void) const;
BOOL IsImag(void) const;
complex_d& operator=(const complex_d& rhs);
complex_d& operator+=(const complex_d& rhs);
complex_d& operator-=(const complex_d& rhs);
complex_d& operator*=(const complex_d& rhs);
complex_d& operator/=(const complex_d& rhs);
complex_d operator+(const complex_d& rhs);
complex_d operator-(const complex_d& rhs);
complex_d operator*(const complex_d& rhs); // ambiguous error here...
complex_d operator/(const complex_d& rhs);
complex_d operator-(void); // unary
complex_d& operator=(const double& rhs);
friend complex_d operator+(const complex_d& lhs, double rhs);
friend complex_d operator+(double lhs, const complex_d& rhs);
friend complex_d operator-(const complex_d& lhs, double rhs);
friend complex_d operator-(double lhs, const complex_d& rhs);
friend complex_d operator*(const complex_d& lhs, double rhs); // ... and here also ambigous
friend complex_d operator*(double lhs, const complex_d& rhs);
friend complex_d operator/(const complex_d& lhs, double rhs);
friend complex_d operator/(double lhs, const complex_d& rhs);
friend BOOL operator==(const complex_d& lhs, double rhs);
friend BOOL operator==(double lhs, const complex_d& rhs);
friend BOOL operator!=(const complex_d& lhs, double rhs);
friend BOOL operator!=(double lhs, const complex_d& rhs);
friend BOOL operator==(const complex_d& lhs, const complex_d& rhs);
friend BOOL operator!=(const complex_d& lhs, const complex_d& rhs);
};
The two operators in question are marked as ambigous but I don't see why. Originally this class was written as a template which in fact only was instantiated with double type. So I de-templated the complex_d class which results in the definition above. It compiled w/out errors and warnings in MSC environment using MS Visual C++ .NET 2002 but I get these ambiguity errors with g++ 4.2.1 now.
I'm quite long off writing code with overloading operators in C++ and I experimented a lot rewriting the two definitions of the * operators. The main problem is I don't understand why this is ambiguous. For:
qSt * dVal
a complex_d has to be multiplied with a double variable value and the result has to be returned as complex_d. Therefore the friend operator * has to be evaluated. When I replace the operator
friend complex_d operator*(const complex_d& lhs, double rhs);
with
complex_d operator*(double rhs);
I get another error telling me that a class member or enum is needed as parameter. It is also not possible to omit the second operator in question because it is also needed at another place in the code.
Is anyone out there who can tell me how to get out of this dilemma?

I see two ways to fix this (there's probably more):
Add explicit to the constructor:
explicit complex_d(double re = 0, double im = 0);
Remove the friend operator*().
The C++ std::lib went with solution #2 for std::complex.

Related

template class 's non-member template operator overload syntax [duplicate]

I have a linking problem when using a home-made Complex class.
Class definition:
template<class T>
class Complex
{
public:
Complex(const T real = 0, const T imag = 0);
Complex(const Complex<T>& other);
~Complex(void) {};
Complex<T> operator*(const Complex<T>& other) const;
Complex<T> operator/(const Complex<T>& other) const;
Complex<T> operator+(const Complex<T>& other) const;
Complex<T> operator-(const Complex<T>& other) const;
friend void operator*=(const Complex<T>& z,const Complex<T>& other);
friend void operator/=(const Complex<T>& z,const Complex<T>& other);
friend void operator+=(const Complex<T>& z,const Complex<T>& other);
friend void operator-=(const Complex<T>& z,const Complex<T>& other);
void operator=(const Complex<T>& other);
friend T& real(Complex<T>& z);
friend T& imag(Complex<T>& z);
friend T abs(Complex<T>& z);
friend T norm(Complex<T>& z);
private:
T real_;
T imag_;
};
Implementation of abs:
template<class T>
T abs(Complex<T>& z)
{
return sqrt(z.real_*z.real_ + z.imag_*z.imag_);
}
I use the function abs like this : if(abs(z) <= 2).
Here are some errors I get:
Error 4 error LNK2001: unresolved external symbol "long double __cdecl abs(class Complex<long double> &)" (?abs##YAOAAV?$Complex#O###Z) C:\Users\Lucas\Documents\Visual Studio 2012\Projects\Fractals\Fractals\Main.obj Fractals
Error 3 error LNK2001: unresolved external symbol "long double & __cdecl imag(class Complex<long double> &)" (?imag##YAAAOAAV?$Complex#O###Z) C:\Users\Lucas\Documents\Visual Studio 2012\Projects\Fractals\Fractals\Main.obj Fractals
I get the same errors when using Complex<float> instead of Complex<long double>. I work with Visual C++ 2012. I would be really glad if you give me some hint on how to fix this. Thank you.
The function declared as
template <typename T>
class Complex {
// ...
friend T abs(Complex<T>& z);
// ...
};
is not a function template! It looks a bit like one as it is nested within a class template but that isn't quite enough. Here is what you probably meant to write:
template <typename T> class Complex;
template <typename T> T abs(Complex<T>&);
template <typename T>
class Complex {
// ...
friend T abs<T>(Complex<T>& z);
// ...
};
Alternatively, you could implement abs() when declaring it as friend.

Inline operator!= undefined reference

I am getting the compiler error undefined reference to when attempting to inline operator!= as a friend function.
Here is an example:
// color.hpp
class Color
{
friend bool operator==(const Color& lhs, const Color& rhs);
inline friend bool operator!=(const Color& lhs, const Color& rhs);
};
// color.cpp
bool operator==(const Color& lhs, const Color& rhs)
{
}
inline bool operator!=(const Color& lhs, const Color& rhs)
{
}
I cannot implement the operators in the header file, as this creates multiple definition errors.
I am compiling with --std=c++11, g++ 5.2.
Remove the inline from the class definition.
After the class definition, in the header file, add the following:
inline bool
operator!=(const Color& lhs, const Color& rhs)
{
return !(lhs == rhs);
}
Remove the definition in the source file.

Exporting templated inline functions - definition of function dllimport not allowed

I'm trying to implement math library but I'm stuck on exporting. I have a template class for 2-dimensional vector:
vector2.h:
template <typename T>
class GE_API Vector2
{
public:
T x;
T y;
// Indexation
T& operator [] (const size_t i);
const T& operator [] (const size_t i) const;
bool operator == (const Vector2& v) const;
bool operator != (const Vector2& v) const;
// Negation
const Vector2 operator - () const;
// Assignement
const Vector2& operator = (const Vector2& v);
const Vector2& operator += (const Vector2& v);
const Vector2& operator -= (const Vector2& v);
template <typename S>
const Vector2& operator *= (const S& s);
template <typename S>
const Vector2& operator /= (const S& s);
const Vector2 operator + (const Vector2& v) const;
const Vector2 operator + (const T& s) const;
const Vector2 operator - (const Vector2& v) const;
const Vector2 operator - (const T& s) const;
template <typename S>
const Vector2 operator * (const S& s) const;
const Vector2 operator * (const Vector2& v) const;
template <typename S>
const Vector2 operator / (const S& s) const;
const Vector2 operator / (const Vector2& v) const;
};
template <typename T>
GE_API const T dot(const Vector2<T>& a, const Vector2<T>& b);
template <typename T>
GE_API const T length(const Vector2<T>& v);
//..and other functionality
#include <vector2.inl>
Definitions of operators and functions are in separate file vector2.inl which is included in header file. GE_API is standard dllimport/export macro. Problem is that when I try to export this class and functions defined in vector2.h header file I'm getting errors on definitions of operators that definition of dllimport function is not allowed. Why is that and how to fix this?
I think in this case you don't need to specify dllimport/export for your class.
Because all source code will be avaliable to the user and only anoe thing that he heeds is to include vactor2.h header into his project.

Why is std::complex real member function not const?

Any reason for the member functions "real" and "imag" in the std::complex class not to be const?
There are two overloads for real in the complex class template:
T real() const;
void real(T);
The first on is const, so that can't be what you're asking about.
The second one, which takes a T argument and returns nothing, is not const, because it's a "setter" method—the whole point of it is to change the state of the object, so it had better not be const.
Let's look at the C++ Standard:
C++ 2011 Section 26.4.2 Class Template Complex
namespace std {
template<class T>
class complex {
public:
typedef T value_type;
complex(const T& re = T(), const T& im = T());
complex(const complex&);
template<class X> complex(const complex<X>&);
T real() const;
void real(T);
T imag() const;
void imag(T);
complex<T>& operator= (const T&);
complex<T>& operator+=(const T&);
complex<T>& operator-=(const T&);
complex<T>& operator*=(const T&);
complex<T>& operator/=(const T&);
complex& operator=(const complex&);
template<class X> complex<T>& operator= (const complex<X>&);
template<class X> complex<T>& operator+=(const complex<X>&);
template<class X> complex<T>& operator-=(const complex<X>&);
template<class X> complex<T>& operator*=(const complex<X>&);
template<class X> complex<T>& operator/=(const complex<X>&);
};
}
I'd say that it's pretty clearly stated that std::complex::real() and std::complex::imag() are const methods.

Linking error with friend function in template class

I have a linking problem when using a home-made Complex class.
Class definition:
template<class T>
class Complex
{
public:
Complex(const T real = 0, const T imag = 0);
Complex(const Complex<T>& other);
~Complex(void) {};
Complex<T> operator*(const Complex<T>& other) const;
Complex<T> operator/(const Complex<T>& other) const;
Complex<T> operator+(const Complex<T>& other) const;
Complex<T> operator-(const Complex<T>& other) const;
friend void operator*=(const Complex<T>& z,const Complex<T>& other);
friend void operator/=(const Complex<T>& z,const Complex<T>& other);
friend void operator+=(const Complex<T>& z,const Complex<T>& other);
friend void operator-=(const Complex<T>& z,const Complex<T>& other);
void operator=(const Complex<T>& other);
friend T& real(Complex<T>& z);
friend T& imag(Complex<T>& z);
friend T abs(Complex<T>& z);
friend T norm(Complex<T>& z);
private:
T real_;
T imag_;
};
Implementation of abs:
template<class T>
T abs(Complex<T>& z)
{
return sqrt(z.real_*z.real_ + z.imag_*z.imag_);
}
I use the function abs like this : if(abs(z) <= 2).
Here are some errors I get:
Error 4 error LNK2001: unresolved external symbol "long double __cdecl abs(class Complex<long double> &)" (?abs##YAOAAV?$Complex#O###Z) C:\Users\Lucas\Documents\Visual Studio 2012\Projects\Fractals\Fractals\Main.obj Fractals
Error 3 error LNK2001: unresolved external symbol "long double & __cdecl imag(class Complex<long double> &)" (?imag##YAAAOAAV?$Complex#O###Z) C:\Users\Lucas\Documents\Visual Studio 2012\Projects\Fractals\Fractals\Main.obj Fractals
I get the same errors when using Complex<float> instead of Complex<long double>. I work with Visual C++ 2012. I would be really glad if you give me some hint on how to fix this. Thank you.
The function declared as
template <typename T>
class Complex {
// ...
friend T abs(Complex<T>& z);
// ...
};
is not a function template! It looks a bit like one as it is nested within a class template but that isn't quite enough. Here is what you probably meant to write:
template <typename T> class Complex;
template <typename T> T abs(Complex<T>&);
template <typename T>
class Complex {
// ...
friend T abs<T>(Complex<T>& z);
// ...
};
Alternatively, you could implement abs() when declaring it as friend.