|
Boost : |
From: Maarten Keijzer (mak_at_[hidden])
Date: 2000-03-08 09:56:12
At 05:58 AM 3/8/00 +0100, you wrote:
>Maarten Keijzer wrote:
>
>> in
>> operators.hpp temporarily hacked a less_than_comparable2<interval<RealType,
>> Traits>, RealType > class, added std::min and std::max etc.)
>
>Here we go again.
>
>I have decided to face the inevitable: we need "2" versions of each such
>operator base class which currently has a specialization. Too many people
>need the functionality for MSVC6.
And might not need it for MSVC12 anymore... But kidding aside, I just found
an interesting loophole that does compile under MSVC6, but that changes the
functionality of operators.hpp dramatically. I can't oversee all
implications of this change so I'll just give you some code that does
compile and some of the implications I can see. Feel free to burn this
proposal if it is too flawed.
MSVC is perfectly content with for instance a class addable that defines
operator+= rather than operator+. So the following compiles and works.
namespace boost
{
template <class T, class U = T>
class addable_test
{
friend T& operator+=( T& x, const U& y ) { return x = x + y; }
};
}
struct AddTester : boost::addable_test<AddTester>,
boost::addable_test<AddTester, double>
{
AddTester() : v(0.0) {}
friend AddTester operator+(AddTester a, const AddTester& b)
{ a.v += b.v; return a; }
friend AddTester operator+(AddTester a, double b) { a.v += b; return a; }
double v;
};
It's a bit odd to have a friend assignment operator, and it is also agains
common practice to have the non-assigning operators do the actual work and
there might be some performance penalties associated with this (lot's of
copying), but at least it works (but then again, I only tested it with MSVC
which is not much of an authority on standard C++).
Another disadvantage is that the symmetrical definition of operator+ is
lost, so that this construction merely saves a single function instead of
the two. The corresponding advantage is that you now can have two classes
working together that both derive from boost::operators without having an
ambiguity as is the case now.
But I also see a big advantage: this construction is very friendly for
expression-templates techniques. If you define your expression templates in
the operator+ etc, you only have to define the actual calculation in an
appropriate operator= and you're there. boost::operators will then save you
the odd few keystrokes for defining all appropriate assignment operators.
The comparison classes like less_than_comparable need to be careful not to
define functions like operator<(const U& a, const T& b) as this will lead
to a infinite-loop (ok, stack overflow) when U == T (and helpfully, MSVC
ignores the fact that there are two equally valid definitions). So you can
say:
interval<double> a; // derived from less_than_comparable
double b;
if (a < b) ...
but not
if (b < a) ...
So that's pretty bad. But then again (b > a), (a > b) and all those do
work. Maybe -- that is if this proposal is worth anything at all -- we need
to restrict the boost::operator library to just define the pattern op(T, U)
and never op(U,T). It would be a pity to lose op(U,T) for built-in types U,
but for user-defined types U it can be argued that defining op(U, T) in
class T is in general a bad idea.
But as I said, I cannot oversee all the implications (although during the
writing of this mail I came across more and more, almost to the point of
not sending it at all), so it might just be a bad idea.
-Maarten-
******************************************
Maarten Keijzer
DHI Water & Environment
Agern Allé 11
DK-2970 Hørsholm
Denmark
Phone: +45 45 16 92 00
Direct phone: +45 45 16 93 52
Fax: +45 45 16 92 92
email: mak_at_[hidden]
******************************************
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk