Boost logo

Boost :

From: Dave Abrahams (abrahams_at_[hidden])
Date: 2000-04-30 15:29:57


on 4/30/00 3:01 PM, Aleksey Gurtovoy at alexy_at_[hidden] wrote:

> 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.

I see that now. Okay, great.

>> 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?

Unfortunately, Microsquish actually distinguishes between 'class' and
'struct' in its link names, or it wouldn't matter. Once you call something a
struct or class, if you want maximum compatibility you have to keep it.

On the other hand, I don't mind shaking things up for Microsquish users once
in a while ;)
Using 'struct' everywhere would make things much cleaner.

>> 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; }
> };

Good, good. I see why all of this should work so far.

> 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.

You could always add yet another B type parameter to check for all
combinations of operator templates ;(.

I have two questions remaining:
1. Is this worth all the complication (it is *very* complex)?
2. What if there's no partial specialization? What are we left with? All the
same stuff without the 2-operand templates named without the trailing '2'?

-Dave


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