This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: Remove algo duplication
- From: Marc Glisse <marc dot glisse at inria dot fr>
- To: Christopher Jefferson <chris at bubblescope dot net>
- Cc: libstdc++ <libstdc++ at gcc dot gnu dot org>, Paolo Carlini <paolo dot carlini at oracle dot com>, François Dumont <frs dot dumont at gmail dot com>
- Date: Mon, 16 Sep 2013 13:57:09 +0200 (CEST)
- Subject: Re: Remove algo duplication
- Authentication-results: sourceware.org; auth=none
- References: <52264074 dot 2050502 at gmail dot com> <alpine dot DEB dot 2 dot 10 dot 1309081625460 dot 3536 at laptop-mg dot saclay dot inria dot fr> <522E246F dot 5040608 at gmail dot com> <E2836BBC-F90D-4AE5-AAAB-EB3242BF030D at oracle dot com> <CA+jCFLtpCASpP1NTru=__hOQo5O-uj0m82YDqmB2wBYxspcQxA at mail dot gmail dot com> <alpine dot DEB dot 2 dot 10 dot 1309151125180 dot 3593 at laptop-mg dot saclay dot inria dot fr> <CA+jCFLsgUS3x0AVQDvn1OUgkYt6EJJojUrL4xrtVo9XQwq8J6A at mail dot gmail dot com>
- Reply-to: libstdc++ at gcc dot gnu dot org
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