Boost logo

Boost :

Subject: Re: [boost] [range] [general] making member functions SFINAE-friendly
From: Neil Groves (neil_at_[hidden])
Date: 2013-02-20 15:55:30

On Wed, Feb 20, 2013 at 2:57 PM, Thorsten Ottosen <
thorsten.ottosen_at_[hidden]> wrote:

> On 20-02-2013 00:11, Neil Groves wrote:
> To me this seems simpler than having more base classes, but comes at the
>> cost of eventually breaking backward compatibility.
>> I've been very wary to discuss this since I've never managed to convince
>> myself sufficiently that this is the optimal solution. I'm extremely
>> reluctant to break interfaces, but with a sufficient period for the
>> deprecation perhaps the community would prefer this option?
>> I have been wrestling with this issue for some time, and think that
>> deprecating the member function size() on iterator_range combined with the
>> provision of an extensible boost::size(rng) that has O(1) would be a
>> reasonable compromise. We have boost::distance already which provides the
>> complexity guarantee equivalent of std::distance. If we add
>> boost::size(rng) that delegates to range_size then I could provide
>> implemetentations for the standard containers, and users could augment the
>> behaviour to keep O(1) size for other containers, and could even choose to
>> loosen the performance guarantee if they desired.
> I'm very keen to hear the thoughts of current users since I am unsure how
>> much code relies upon iterator_range member size() function. Additionally
>> I
>> bet Thorston and Nate have some great ideas.
> -1 for the idea of introducing another base class.
I agree. My suggestion didn't have a new base class. I think by making
boost::size(rng) call range_size(rng) we can provide an extension method
similar to that already provided for boost::begin(rng) and boost::end(rng).
Then generic algorithms can be written by using boost::size(rng) knowing
that the optimal solution
will be selected. This also allows the users to customise and chose
trade-offs in generic support versus algorithm complexity.

> Breaking the interface could be done, but I guess we would have 2 or three
> releases before it actually came into the code? What's the official Boost
> policy on this matter? I don't know how much that time line would help
> Jonathan's clients or those writing generic code that accepts an O(n) time
> size operation.
Since the solution I propose is not a new base-class it solves the problem
both more completely and immediately. The users of Boost.Range would simply
be encouraged to use the non-member function. In parallel the member
function size() on iterator_range can be deprecated and subsequently

> Having a tool for getting the O(1) size() from containers which currently
> fail to work with boost::size() would be good. However, how do we do that
> without concept-based overloading?
As dull as it may seem I think, just allowing a simple extension point
would be fine. We could simply provide the standard containers and
container writers could implement an overload. This is probably simpler
than adding additional trait classes etc. I am torn between a simple ADL
extension point and combining this with a n additional type_trait. It seems
the idiomatic thing to do would be to use a trait, but when I think through
the use-cases the code required for the container developer is longer with
the trait.

Currently I'm leaning toward just providing a simple ADL extension point.
It would address this problem and one of the biggest niggles I come across
when writing generic algorithm code.

> -Thorsten
Neil Groves

Boost list run by bdawes at, gregod at, cpdaniel at, john at