Re: Compilation failure involving template operator
On 4 Jul., 10:49, Edward Diener <eldie...@tropicsoft.invalid> wrote:
The code below surprisingly for me fails compilation on Comeau C++ and
VC++ 9:
----------------------------------------------------------
struct XTestChar
{
operator char() const { return c; }
char c;
};
template <class T> struct YTestTemplate { };
template <class T>
YTestTemplate<T> &
operator *= (YTestTemplate<T> & first,T second)
{
return(first);
}
XTestChar xtest;
YTestTemplate<char> ytest;
void AFunction()
{
ytest *= xtest;
}
------------------------------------------------------------
[..]
I would have thought that the C++ compiler would always deduce T in the
operator*= to be 'char', from the fact that 'ytest' is clearly
'YTestTemplate<char>' and then use XTestChar's char conversion operator
to pass a 'char' to the operator *= function second parameter. Why is
this not allowed ? Are templated operators not allowed to do conversions
when a type is deduced ?
The allowed operator overloads behave like other function
templates (as explained in detail within [over.match.oper]).
You have decided for a non-member operator overload
of operator*=. The way you defined this template has
the effect that the compiler is supposed to deduce
the template parameter T for both it's T-dependent
arguments. Doing so, it finds T=char for the first and
T=XTestChar for the second. Since this is a function
template, no conversions are tried.
You have different ways to solve this problem, e.g.:
1) Use a member function overload like this:
template <class T> struct YTestTemplate {
YTestTemplate &
operator *=(T second) {
return *this;
}
};
This is a non-template member-function of
YTestTemplate, therefore the compiler looks
only at the member candidates of YTestTemplate
and finds only one. Note that in this case
the T of the member *= is fixed and no
T deduction of this argument is done. Now
the compiler looks for conversions to this T
and successfully finds the conversion function,
leading to success.
2) Use a non-member overload like as you started
with, but this time ensure that the second
argument is in a non-deduced context, e.g. like
this
template<class T> struct identity { typedef T type; };
template <class T>
YTestTemplate<T> &
operator *= (YTestTemplate<T> & first, typename identity<T>::type
second)
{
return first;
}
This time your original program should be well-formed,
because the compiler does no longer attempt to deduce
two (potentially different) parameters types with T.
HTH & Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]