Well, as far as I can see the documentation says only that the
operation has to compile, not that operator /= must be a
member.
That's true in the tables, but the introductory documentation
does make a point of them being member functions. (Of course,
logically, it should be documented as a constraint.)
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.
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 ;
}
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.
#include <boost/config.hpp>
#ifndef BOOST_HAS_NRVO
#define BOOST_FORCE_SYMMETRIC_OPERATORS
#endif
#include <boost/operators.hpp>
I think that BOOST_FORCE_SYMMETRIC_OPERATORS is designed to be
set by you. Just define it, before including any Boost headers,
and I think you should be OK. (I can't test it, because for my
compiler here, BOOST_HAS_NRVO is set, systematically, so unless
I use a hack like the above to undefine it, your code works.)
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:
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:
perator/ (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).