
On 23/04/14 16:28, Neil Groves wrote:
On Wed, Apr 23, 2014 at 2:13 PM, Albert Yiamakis <vkicefire@gmail.com>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/ext...
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