r203293 - [C++11] Revert uses of lambdas with array_pod_sort.

Richard Smith richard at metafoo.co.uk
Sun Mar 9 18:55:26 PDT 2014


On Sun, Mar 9, 2014 at 6:37 PM, Arthur O'Dwyer <arthur.j.odwyer at gmail.com>wrote:

> On Sun, Mar 9, 2014 at 12:14 AM, Ahmed Charles <acharles at outlook.com>
> wrote:
> > ________________________________
> >> Date: Fri, 7 Mar 2014 14:15:32 -0800
> >> Subject: Re: r203293 - [C++11] Revert uses of lambdas with
> array_pod_sort.
> >> From: richard at metafoo.co.uk
> >> To: arthur.j.odwyer at gmail.com
> >> CC: cfe-commits at cs.uiuc.edu
> >>
> >> On Fri, Mar 7, 2014 at 2:10 PM, Arthur O'Dwyer <
> arthur.j.odwyer at gmail.com> wrote:
> >>
> >>> - The spaceship operator <=> is equivalent to (a < b) ? -1 : (a> b)
> >>
> >> The more usual idiom of
> >>
> >>    if (!=)
> >>      return <
> >>
> >> naturally extends to lexicographical comparisons of multiple things. I
> >> don't see how to do that with (a<b?-1:a>b).
>
> Recognizing that this is off-topic and also completely "personal
> style", I think your classification of (a != b) ? (a < b) ? -1 : +1 :
> 0 as "more usual" is subjective.


I don't think I've seen it written like that. I've seen this:

if (a.x != b.x) return a.x < b.x ? -1 : 1;
if (a.y != b.y) return a.y < b.y ? -1 : 1;
// ...
return 0;


> In my subjective experience, (a < b)
> ? -1 : (a > b) is "more usual". ;)
>
> If you have multiple fields in your struct, then (as Ahmed suggests)
> the most stylish idiom is to 'tie' your fields together.
>

If you assume that your fields have < and == with roughly equal costs (and
are complex enough that the two approaches won't get optimized to the same
code), your 'tie' approach is 2-4x more expensive. If you have N fields,
the ==/< approach uses at most N+1 comparisons. The 'tie' approach uses up
to 2N comparisons for each < operation, and does either 1 or 2 of those.

    template<typename T> int spaceship(const T& a, const T& b) {
> return (a < b) ? -1 : (a > b); }  // trivial
>
>     struct S {
>         int x, y, z;
>         decltype(auto) toTuple() const { return std::tie(x,y,z); }  //
> unfortunately annoying to type pre-C++14, but still trivial
>     };
>
>     bool operator< (const S& a, const S& b) { return a.toTuple() <
> b.toTuple(); }  // trivial
>     int spaceship(const S& a, const S& b) { return
> spaceship(a.toTuple(), b.toTuple()); }  // trivial
>
> Unfortunately I don't think C++1y has added any special library
> support for the spaceship function, which means all the solutions
> named so far involve computing (a.x==b.x), (a.y==b.y), etc., up to the
> point of the first difference, TWICE. You can work around the lack of
> std::spaceship (or std::tuple::tail or whatever you choose as your
> missing primitive) and make the stylish solution also efficient, but I
> won't write it here because the guts are embarrassingly ugly. :P
>
> -Arthur
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140309/6cf85883/attachment.html>


More information about the cfe-commits mailing list