r203293 - [C++11] Revert uses of lambdas with array_pod_sort.
Ahmed Charles
acharles at outlook.com
Sun Mar 9 00:14:51 PST 2014
________________________________
> 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<mailto:arthur.j.odwyer at gmail.com>> wrote:
> On Fri, Mar 7, 2014 at 1:51 PM, Benjamin Kramer
> <benny.kra at googlemail.com<mailto:benny.kra at googlemail.com>> wrote:
> >
> > [C++11] Revert uses of lambdas with array_pod_sort.
> >
> > Looks like GCC implements the lambda->function pointer conversion
> differently.
>
> > - llvm::array_pod_sort(DeferredLocs.begin(), DeferredLocs.end(),
> > - [](const DeferredLocsTy::value_type *p1,
> > - const DeferredLocsTy::value_type *p2) {
> > - if (p1->second->getLocStart() != p2->second->getLocStart())
> > - return p1->second->getLocStart() < p2->second->getLocStart()
> ? -1 : 1;
> > - return 0;
> > - });
> > + llvm::array_pod_sort(DeferredLocs.begin(), DeferredLocs.end(),
> SrcCmp);
>
> Incidentally, I like the bag-of-idioms
>
> auto *byLocation =
> +[](const DeferredLocsTy::value_type *p1, const
> DeferredLocsTy::value_type *p2) -> int {
> return (p1->second->getLocStart() <
> p2->second->getLocStart() ? -1 : (p1->second->getLocStart()>
> p2->second->getLocStart());
> };
> llvm::array_pod_sort(DeferredLocs.begin(), DeferredLocs.end(),
> byLocation);
>
> That is,
> - Name the out-of-line lambda after the predicate it implements (in
> this case sorting "byLocation")
> - I bet you'll find compilers are happier with the explicitly
> function-pointer'ized "+[]" than with "[]" alone
>
> I bet the opposite. MSVC (non-conformingly) gives lambdas three
> conversions to function pointers with different calling conventions,
> and this won't compile there.
>
> - 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).
I don't either, but if (!(a < b) && !(b < a)) != (a == b), then you need to do something like:
struct S {
int a, b, c;
};
bool operator<(const S& a, const S& b) {
return a.a < b.a || (!(b.a < a.a)
&& (a.b < b.b || (!(b.b < a.b)
&& (a.c < b.c))));
}
Which is ugly and hard to get right. Hence why I'd recommend using:
bool operator<(const S& a, const S& b) {
return std::tie(a.a, a.b, a.c) < std::tie(b.a, b.b, b.c);
}
Which does the same thing.
More information about the cfe-commits
mailing list