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