Boost logo

Boost :

From: Aleksey Gurtovoy (alexy_at_[hidden])
Date: 2000-04-30 15:01:13


Dave Abrahams <abrahams_at_[hidden]> wrote:
> I see the following potential problems:
>
> 1. What happens when you try to use the 2-type version of addable with
> another class derived from one of the operators? For example, suppose you
> have a variable precision integer class that you want to be able to
combine
> with a rational? Don't you end up improperly detecting the 2nd type as an
> operators base class instead of a 2nd operand type?
>
No, I wouldn't. I would be if I determined
'is_boost_operators_template<U>::value' by using the old technique for
determining whenever U is derived from 'boost::detail::empty_base', but
luckily I very quickly realized that this won't work in cases you've
described above. If it worked, it would require less code and the code would
be less error-prone. In the current version you have to specialize
'is_boost_operators_template<U>' for each new operators template you add to
the header. If you wouldn't (forgot), we are out of luck.

> 2. Lack of public derivation means that forward_iterator_helper is-not-a
> std::iterator<...>
>
opps... :) I missed that by moving std::iterator to a deep level of
hierarchy I lose public inheritance "privilege" granted by 'struct' in the
'boost::forward_iterator_helper' declaration. There are two ways to fix it:
1) by changing private inheritance from the last template parameter (': D'
now) to a public one;
2) by defining all operators templates as 'struct' instead 'class'; some of
them, e.g. incrementable are already defined as 'struct'; if no one forward
declared these classes in his code (I don't see any point to do that), then
probably this modification will be safe for the users.
Your opinion?

> 3. Seems like you'd have unpredictable effects for users that get used to
> the usual case of chaining addable<T, multipliable<T, ... if the last item
> in the chain is some other base class they want. For example, what does
this
> do?
>
> class Y {};
> class X : public addable<X, multipliable<X, Y> > { };
>
It works :). At least, the following one works:

class Y {};
class X : boost::addable<X, boost::multipliable<X, Y> > {
public:
 X& operator+=( const X& ) { return *this; }
 X& operator*=( const Y& ) { return *this; }
 };

And this one works too:

class Y : addable<Y> {
public:
 Y& operator+=( const Y& ) { return *this; }
};

class X : addable<X, multipliable<X, Y> > {
public:
 X& operator+=( const X& ) { return *this; }
 X& operator*=( const Y& ) { return *this; }
 };

We *will* have 'unpredictable' results in cases like this (and that was one
of the issues I mentioned in my previous article):

class Y {};
class X : addable<X, multipliable<X, Y>, subtractable<X, Y> > {
 public:
 X& operator+=( const X& ) { return *this; }
 X& operator*=( const Y& ) { return *this; }
 };

More exactly, in that case 'subtractable<X, Y>' will be ignored and have no
effect on the X definition.
And this one just will not be accepted by compiler:

class Y {};
class X : addable<multipliable<X, Y> > {
public:
 X& operator+=( const X& ) { return *this; }
 X& operator*=( const Y& ) { return *this; }
 };

Probably in the first case we also need some diagnostic from compiler.

--Aleksey


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk