Re: User defined conversion to builtin type gives l-value?
James Kanze schrieb:
On Apr 11, 9:34 pm, Arne Mertz <n...@arne-mertz.de> wrote:
SG schrieb:
On 11 Apr., 18:30, Arne Mertz <n...@arne-mertz.de> wrote:
You either write
return T(u) / t; // suggested previously
or you write
T temp = u;
temp /= t;
return temp;
Unfortunately, *I* write nothing there. The function is part
of the boost libraries (boost/operators.hpp, line 240). It is
only used in the absence of two #defines, so as a workaround I
had to check for those defines and set one of them explicitly.
Have you actually read the documentation of Boost::operators?
They provide operators for user defined classes. Not in the
best way, of course---you really want to use the Barton and
Nackman trick here, and provide them as friends of a base
class. But that's not the point here: if you instantiate e.g.
operator/ with X as the first template argument, then it is a
pre-condition that X has a member function operator/=.
Otherwise, you're not using the library as specified.
Well, as far as I can see the documentation says only that the
operation has to compile, not that operator /= must be a member.
Of course, I can't find any way you could reasonably use the
library as it is specified---you need operator/ to be somewhere
where ADL will find it, and ADL will not look into namespace
boost. (That's why the Barton and Nackman trick is preferred.)
And of course, there really isn't any good reason to not support
classes with operator/= as a free function---arguably, it should
be a free function, because that is the only way to make it
require an lvalue.
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 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:
#include <boost/config.hpp>
#ifndef BOOST_HAS_NRVO
#define BOOST_FORCE_SYMMETRIC_OPERATORS
#endif
#include <boost/operators.hpp>
But what puzzles me is that if the left template argument is a
userdefined 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;
}
greets
A