By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,797 Members | 1,794 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,797 IT Pros & Developers. It's quick & easy.

<complex> : no match for 'operator*' // conversion operator double()

P: n/a
Hello,

I'd like to understand why the following code does not compile. It
looks like a strangeness in connection with overload resolution for the
<complex> header:
The conversion operator double() of class B is called for the member
complex::operator*=(double) as expected, but not for operator*(complex,
double).

The effect is, that the template matching (or overload resolution)
fails. Error message:
complex_double_conversion.cpp: In function 'int main()':
complex_double_conversion.cpp:19: error: no match for 'operator*' in 'z
* x'

Tested with g++ 4.0.2 20050901 (prerelease) on (SUSE Linux) and others.
Do <you> know a reason/remedy for this behaviour? Thanks in advance.

//------------------------complex_double_conversion.cpp-------------------------
#include<complex>

class B {
double v;
public:
operator double() const { return v; } // conversion operator
B(double _v) : v(_v) {}
};

int main() {
std::complex<double> z(0,1);
B x(0.5);

// next line works due to complex<_Tp>&
complex<_Tp>::operator*=(const _Tp&)
// the conversion operator of class B is used
z*=x;

// the next line does not compile
std::complex<double> y( z*x );

// only with cast: z*((double) x)
//
// although in <complex> there is
// template<typename _Tp>
// inline complex<_Tp> operator*(const complex<_Tp>& __x, const
_Tp& __y)
// { return complex<_Tp> (__x) *= __y; }
//
return 0;
}
//-----------------------------------------------------------------------------------------

Jun 23 '06 #1
Share this Question
Share on Google+
2 Replies


P: n/a
Arvid Requate wrote:
Hello,

I'd like to understand why the following code does not compile. It
looks like a strangeness in connection with overload resolution for the
<complex> header:
The conversion operator double() of class B is called for the member
complex::operator*=(double) as expected, but not for operator*(complex,
double).

The effect is, that the template matching (or overload resolution)
fails. Error message:
complex_double_conversion.cpp: In function 'int main()':
complex_double_conversion.cpp:19: error: no match for 'operator*' in 'z
* x'

Tested with g++ 4.0.2 20050901 (prerelease) on (SUSE Linux) and others.
Do <you> know a reason/remedy for this behaviour? Thanks in advance.
The operator* function you want to call is a non-member as follows:
template<class T>
complex<T> operator*(const complex<T>& lhs, const T& rhs);

Template argument deduction fails because it requires that the arguments
are exact matches for the deduced parameter types (with a few
exceptions), but B is not similar enough to double const& (user defined
conversions aren't considered).

The easiest fix is to write a suitable function (in the same namespace
as B so that it is found by ADL), something like:

complex<double> operator*(const complex<double>& lhs, const B& rhs)
{
return lhs * static_cast<double>(rhs);
}

Tom

//------------------------complex_double_conversion.cpp-------------------------
#include<complex>

class B {
double v;
public:
operator double() const { return v; } // conversion operator
B(double _v) : v(_v) {}
};

int main() {
std::complex<double> z(0,1);
B x(0.5);

// next line works due to complex<_Tp>&
complex<_Tp>::operator*=(const _Tp&)
// the conversion operator of class B is used
z*=x;

// the next line does not compile
std::complex<double> y( z*x );

// only with cast: z*((double) x)
//
// although in <complex> there is
// template<typename _Tp>
// inline complex<_Tp> operator*(const complex<_Tp>& __x, const
_Tp& __y)
// { return complex<_Tp> (__x) *= __y; }
//
return 0;
}
//-----------------------------------------------------------------------------------------

Jun 23 '06 #2

P: n/a
* Arvid Requate:

I'd like to understand why the following code does not compile. [snip]
//------------------------complex_double_conversion.cpp-------------------------
#include<complex>

class B {
double v;
public:
operator double() const { return v; } // conversion operator
B(double _v) : v(_v) {}
};

int main() {
std::complex<double> z(0,1);
B x(0.5);

// next line works due to complex<_Tp>&
complex<_Tp>::operator*=(const _Tp&)
// the conversion operator of class B is used
z*=x;

// the next line does not compile
std::complex<double> y( z*x );

// only with cast: z*((double) x)
//
// although in <complex> there is
// template<typename _Tp>
// inline complex<_Tp> operator*(const complex<_Tp>& __x, const
_Tp& __y)
// { return complex<_Tp> (__x) *= __y; }
//
return 0;
}
//-----------------------------------------------------------------------------------------


Template parameter matching does not consider user-defined conversions:
in general types must match exactly (sort of, there's a bit of looseness
in cv-qualification and reference types and so on).

Consider:

template< typename T >
struct Complex { Complex( T = 0, T = 0 ) {} };

template< typename T >
Complex<T> operator*( Complex<T> const&, Complex<T> const& )
{ return Complex<T>(); }

class B
{
double v;
public:
B( double _v ) : v( _v ) {}
operator Complex<double> () const { return v; }
};

int main()
{
Complex<double> z(0,1);
B x(0.5);

// The next line does not compile, not exact match:
z*x;
}

However, adding

template< typename T >
Complex<T> operator*( Complex<T> const& a, B const& b )
{ return a*Complex<T>(b); }

provides an exact match and the code compiles.

A bit more general, adding instead

template< template<class> class C, typename T >
C<T> operator*( C<T> const& a, B const& b )
{ return a*C<T>(b); }

also provides an exact match and the code compiles.

I tried this fix with your original code and it compiles with MSVC 7.1.
However, you'll probably also have to support the opposite argument
order, and other operators such as '+'.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jun 23 '06 #3

This discussion thread is closed

Replies have been disabled for this discussion.