|
Boost : |
Subject: Re: [boost] [range] [general] making member functions SFINAE-friendly
From: Jonathan Wakely (jwakely.boost_at_[hidden])
Date: 2013-02-18 08:17:49
On 18 February 2013 12:57, Andrey Semashev wrote:
>>
>> I'm not "Depending on members of a third party component", I'm writing
>> a generic component and someone tried to use it with
>> boost::iterator_range and asked me why it didn't work.
>
> Then your generic component depends on third party component (which
> happened to be boost::iterator_range). When you try to introspect the
> third party type you should expect all sorts of difficulties, that's
> why I generally discourage it.
I challenge you to implement something like std::allocator_traits
without "introspecting" the template arguments. What I want to do is
a fairly normal generic programming technique, maybe you've heard of
the <type_traits> header, what do you think it's for?
>> The reason iterator_range::size() doesn't use std::distance is given
>> at http://permalink.gmane.org/gmane.comp.lib.boost.devel/193055
>> I think it's a valid choice to only allow size() when its O(1), c.f.
>> std::forward_list, but I think it would be even better to not even
>> define it when it can't be used, c.f. std::forward_list.
>
> Well, the post doesn't give any rationale behind the choice, just that
> it was decided that way. Personally, I don't think that O(N) size() is
> invalid, however slow it may be. You do have list::size(), after all.
Apparently you've missed that std::list::size() is required to be O(1) in C++11.
> I agree that it may seem strange that iterator_range::size() is
> present when it's not working but it is no less stranger that it
> doesn't work when it could. IMHO, the right solution in this case
> would be to fix iterator_range::size() to work in terms of
> std::distance.
Do you also suggest that std::vector::push_front() should be defined,
because it can easily be implemented in terms of v.insert(v.begin(),
x) ?
There is a general design principle in the STL that members functions
are only defined on containers if they are more efficient than doing
the same thing using the more general interfaces. So vector has
push_back() but not push_front(), deque and list have both.
forward_list doesn't have size() or back().
boost::iterator_range has size() but it results in a compile-time
error. This is the worst of all combinations. It would be better to
not define it at all, since users can always use std::distance on its
iterators, which will be optimal for RA iterators anyway.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk