Re: User defined conversion to builtin type gives l-value?
James Kanze schrieb:
On Apr 12, 8:41 pm, Arne Mertz <n...@arne-mertz.de> wrote:
James Kanze schrieb:
In my case it is indeed a free function - it is the builtin
operator/=(double, double). The problem occurs with
dividable2_left<double, X>, which implements
double operator-(X const&, double const&) by converting the X
into double and applying /=
I'm not sure I understand. You can't overload /= for double,
double. The compiler won't even consider user defined overloads
in such cases.
Actually I don't try to overload operator/= for double, double. All
I have to do for the dividable2_left<double,X> is provide the
conversion from X to double.
I know that the mixed arithmetic templates <T,U> should be
declared base classes of T, not of U, but as T is double I
derive U from those templates to make the lookup possible. As
I said, the short form is only used when BOOST_HAS_NRVO and
BOOST_FORCE_SYMMETRIC_OPERATORS are not #defined so at the
moment I make sure that one of the two is defined:
The source is such a confused mess of conditional compilations
that I can't make heads or tails of it. What I think is that
you have two variants (after expansion of all the macros):
T
operator/( T lhs, U const& rhs )
{
return lhs /= rhs ;
}
and
T
operator/( T const& lhs, U const& rhs )
{
T nrv( lhs ) ;
nrv /= rhs ;
return nrv ;
}
these are not the implementations of the operator I have problems
with. its not T op/(T, U), but T op/(U, T).
The two versions of the BOOST_OPERATOR2_LEFT macros are
#if defined(BOOST_HAS_NRVO) || \
defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
friend T operator OP( const U& lhs, const T& rhs )
{ T nrv( lhs ); nrv OP##= rhs; return nrv; }
#else
friend T operator OP( const U& lhs, const T& rhs )
{ return T( lhs ) OP##= rhs; }
#endif
the latter is the version I am having problems with, if T is double.
Both of these should work with T == double. (The first isn't
what I'd consider good coding style, but apparently, it's an
optimization for compilers which don't support NRVO.)
> The case you're interested in is more complex, however, since
> they do an implicit conversion on the value to the left of the
> /=. There's no way this can work for a built-in type.
>
Yes, for the op(T,U) operators thats OK, but for the op(U,T)
apparently it is not, because the U has to be converted into T,
resulting in the problems I described. And note the comment to the
non-nrvo version:
// [...] Note that the implementation of
// BOOST_OPERATOR2_LEFT(NAME) only looks cool, but doesn't provide
// optimization opportunities to the compiler :)
[snip]
But what puzzles me is that if the left template argument is a
user defined type with a free operator/=, the problem does not
occur:
class Y {};
Y& operator/= (Y& lhs, Y const&) { return lhs; }
struct X : public boost::dividable2_left<Y, X>
{
operator Y() const {return Y();}
};
//injected by boost:
//Y boost::operator/ (Y vonst& lhs, X const& rhs)
//{ return X(lhs) /= rhs; }
//
int main()
{
X x;
Y y;
Y e = x / y;
}
Yes it does.
In the beginning of the thread, you mentioned VC++, I think.
I'm not sure, but I seem to recall hearing that VC++ doesn't
enforce the rule about not binding a temporary to a non-const
reference. In which case, the above will work (but the built-in
operator won't, because the rules for lvalues are enforced).
Ah okay, so it's a non-conformity to the standard that makes it work
on MSVC?
greets
A