Boost logo

Boost Users :

Subject: Re: [Boost-users] [Range] Extending the library for a base class and all its derived - enable_if
From: Albert Yiamakis (vkicefire_at_[hidden])
Date: 2014-04-23 11:51:15


On 23/04/14 16:28, Neil Groves wrote:
> On Wed, Apr 23, 2014 at 2:13 PM, Albert Yiamakis <vkicefire_at_[hidden]>wrote:
>
>> Hello,
>>
>> I am looking to make a class, whose definition I cannot touch, model a
>> Range concept. To that end I use method 2,
>>
>>
>> http://www.boost.org/doc/libs/1_55_0/libs/range/doc/html/range/reference/extending/method_2.html
>>
>> However, I am unable to specialize the relevant metafunctions
>> (range_const_iterator, range_mutable_iterator, range_iterator) since
>> they do not have an additional template parameter that would permit me
>> to employ enable_if.
>>
>>
> Generally it isn't necessary to use enable_if to achieve this. There
> support for MFC containers was added by using method 2 to non-intrusively
> add support.

My statement isn't correct - what I really mean is:
I am unable to specialize the relevant metafunctions *for the derived
types of the class*. Of course specializing them for a single class is
not an issue.

> I'm not sure if there is something special about your use-case that stops
> method 2 from working. Perhaps you could take a look at the MFC support in
> Boost.Range to see if this helps you add support for your classes.
>
> If you can provide some code that shows the classes you are trying to make
> support ranges then I'd be happy to try and help.
>

A simple example:

class Base {/* stuff */}; //it is in fact an abstract base class but
shouldn't matter

class Iterator {/* stuff */ }; //will be used to iterate - assume the
default constructed represents end

Now I 'd like all classes that derive from Base to model a Range. I have
only been able to do this by adding the additional template parameter
myself, then this is possible:

namespace boost
{

template <typename C>
struct range_iterator<C, typename enable_if<is_base_of<Base, C> >::type>
{ typedef Iterator type; };

template<typename C>
struct range_const_iterator<C, typename enable_if<is_base_of<Base, C>
>::type>
{ typedef Iterator type; };
}

(Also the following is already possible, without the hack):

template <typename T>
Iterator range_begin(T& foo, typename
boost::enable_if<boost::is_base_of<Base, T> >::type* = NULL) {
    return Iterator(&foo);
}

template <typename T>
Iterator range_end(T& foo, typename
boost::enable_if<boost::is_base_of<Base, T> >::type* = NULL) {
    return Iterator();
}

template <typename T>
Iterator range_begin(const T& foo, const typename
boost::enable_if<boost::is_base_of<Base, T> >::type* = NULL) {
    return Iterator(&foo);
}

template <typename T>
Iterator range_end(const T& foo, const typename
boost::enable_if<boost::is_base_of<Base, T> >::type* = NULL) {
    return Iterator();
}

That works as intended - classes derived from Base can be used as ranges
(the exact concept depends on the Iterator, if I 'm not mistaken).
Can this be achieved without enable_if?

> So far I have never needed an additional parameter. I suspect that we
> don't need the additional parameter, but I'm willing to look at new
> use cases and make appropriate changes if they are warranted.

I could also imagine that the user may wish to use a trait other than
is_base_of to decide whether a class should model a range (but I do not
have a concrete example in mind).

Albert


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net