Remove algo duplication

Marc Glisse marc.glisse@inria.fr
Mon Sep 16 11:57:00 GMT 2013


On Mon, 16 Sep 2013, Christopher Jefferson wrote:

> On 15 September 2013 11:41, Marc Glisse <marc.glisse@inria.fr> wrote:
>> On Sun, 15 Sep 2013, Christopher Jefferson wrote:
>>
>>> I have not looked carefully at predefined_ops.h, but I can show you
>>> some of the previous code which I know has caused problems for this
>>> kind of simplification. I attach it below.
>>>
>>> I agree with Marc, I think templated member functions are the way to
>>> go. For example, I would use objects like this:
>>>
>>> struct __less {
>>> template<typename T, typename U>
>>> bool operator()(T& t, U& u) { return t < u; }
>>> };
>>>
>>> Note the missing 'const' on T& and U& is intentional.
>>
>>
>> That doesn't work for input iterators that return prvalues, does it? (and
>> please let's not rely on the fact that only input iterators can return
>> prvalues)
>
> Good observation. In C++11 we could use perfect forwarding (this is
> "in essence" perfect forwarding in C++03).

std::less<void> now.

> I've not been keeping track of if perfect forwarding really is perfect.

Not quite, that's the point of the example below.

>> One good point about the iterator thing is that you know it does the same
>> thing as using operator< directly, since that's what it does. An example
>> where you can notice a difference is for instance with an input iterator
>> whose operator* returns a prvalue and an operator< that takes its arguments
>> by value. Then with *i<*j you get copy elision, whereas
>> std::less<void>(*i,*j) has to perform 2 moves. We may decide to ignore this
>> difference, I am just giving an example where using __less would be a
>> detectable change for users.
>
> In that situation (I had bugs caused by this before) *i<*j "consumes"
> i and j, and the algorithm probably wants to go on and compare i and j
> to other things in future. Therefore I'm not sure such cases will
> actually usefully work for almost all standard library algorithms (of
> the type we are talking about here).

Note that I said prvalue, not xvalue, so there is no consumption going on. 
vector<bool>::iterator::operator* usually returns a prvalue.

> However, if perfect forwarding preserves current behaviour, then we
> should do that in C++11.

That's the easiest solution, just forward the non-predicate algorithm to 
the predicate-algorithm with std::less<void>() as last argument. It isn't 
completely equivalent to the current separate code, the question is 
whether it is close enough. The version with predicates on iterators is 
perfect (I don't think a user can observe the difference), but then the 
question is if it is too complicated / weird.


-- 
Marc Glisse



More information about the Libstdc++ mailing list