Boost logo

Boost :

From: Joel de Guzman (joel_at_[hidden])
Date: 2003-10-23 18:32:51


Brian McNamara <lorgon_at_[hidden]> wrote:
> I think we're not connecting, but I'm not sure where the problem is.
>
> On Fri, Oct 24, 2003 at 12:32:58AM +0800, Joel de Guzman wrote:
>> Brian McNamara <lorgon_at_[hidden]> wrote:
>>> The general strategy I tend to use for "enable_if-style
>>> meta-predicates" is
>>>
>>> - write a meta-function
>>> is_XXX<T>
>>>
>>> - have an empty base class which serves as the tag name
>>> struct XXX {};
>>>
>>> - have instances of XXX inherit the base class
>>> struct foo : public XXX { ... };
>>>
>>> - have the default implementation of the metafunction use
>>> is_base_and_derived to do the test
>>>
>>> Is this bad? Is there a better way? I have been using this strategy
>>> because
>>
>> If I have control over all classes, I'd defninitely choose that approach.
>> There are cases where you don't. For example, we can't force users
>> to subclass from a base functor class, it has to be a free F type.
>
> But this approach doesn't force this. You can specialize is_XXX<T> for
> your type. The intrusive, inheritance-based approach is simply provided
> to afford a convenient default implementation. This is because I think
> it's easier for me to write
>
> struct foo : public XXX { ... };
>
> rather than
>
> struct foo { ... };
> template <> class is_XXX< foo > { /* something more verbose */ };
>
> or
>
> struct foo { ... };
> template <> class is_XXX< foo > : public /*something*/ {};
>
> Of course, for a 3rd party class "bar", we can always revert to the
> specialization approach to say that "bar is-a XXX". But for classes I
> create, I can use the more syntactically-lightweight inheritance
> approach. In other words, the two styles are complimentary, rather than
> exclusive.
>
> Yes/no/maybe?

If the base-class interface is part of the interface, then it becomes forced.
Let's go back to the start of this mini-thread. Dave (and I) were
worried about this code:

    template <class I>
    inline typename mpl::deref<I>::type
    operator*(I);

The crux of the matter is how to formulate this function so as to
avoid a too general overload. IOTW, the objective is to narrow the
overload set.

I posed 2 solutions:

1) Have all iterators inherit from a base:
 (using CRTP: curriously recurring...)

    template <class I>
    inline typename mpl::deref<I>::type
    operator*(iterator_base<I> const&);

2) Have an is_tuple_iterator<I> meta-function

    template <class I>
    inline typename lazy_enable_if<
        is_iterator<T>
      , mpl::deref<I>
>::type
    operator*(I);

I am well aware of the techniques you have presented. In fact, I
use them a lot *internally* to simplify code. Unfortunately, it is not a
solution for the (mini) problem we are staring at right now, i.e:
as an aid to function overload resolution.

So..., yes, and no, and maybe :-) Please narrow this overload set.
Give me a better formulation of the dereference operator above using
whatever technique and I'll be very happy to say "yes" ;->

Regards,

-- 
Joel de Guzman
http://www.boost-consulting.com
http://spirit.sf.net

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