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