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

Arthur O'Dwyer arthur.j.odwyer at gmail.com
Thu Mar 20 18:45:18 PDT 2014


On Mon, Mar 10, 2014 at 2:46 PM, Richard Smith <richard at metafoo.co.uk> wrote:
> On Mon, Mar 10, 2014 at 12:12 PM, Arthur O'Dwyer <arthur.j.odwyer at gmail.com> wrote:
>> On Sun, Mar 9, 2014 at 9:32 PM, David Blaikie <dblaikie at gmail.com> wrote:
>> > If you're suggesting that tie+op< isn't an idiom we should generally adopt
>> > it'd be nice to build something like it that would be appropriate. (Not sure
>> > if there's something that should be standardized in some form as this idiom
>> > seems like it will be common)
[…]
> More efficient implementation (also untested):
>
> namespace llvm {
> template<typename T> int cmp(const T &a, const T &b) {
>   return a < b ? -1 :
>          a > b ? 1 : 0;
> // or for an efficient implementation that assumes == and < are compatible:
> //  return a == b ? 0 :
> //         a < b ? -1 : 1;
> }
> template<typename ...Args> int cmp(const std::tuple<Args...> &a, const
> std::tuple<Args...> &b);
>
> template<typename Tuple, int I, bool Done = I ==
> std::tuple_size<Tuple>::value>
> struct cmp_impl {
>   int operator()(const Tuple &a, const Tuple &b) const {
>     int result = cmp(std::get<I>(a), std::get<I>(b));
>     return result ? result : cmp_impl<Tuple, I + 1>()(a, b);
>   }
> };
> template<typename Tuple, int I> struct cmp_impl<Tuple, I, true> {
>   int operator()(const Tuple &, const Tuple &) const { return 0; }
> };
> template<typename ...Args>
> int cmp(const std::tuple<Args...> &a, const std::tuple<Args...> &b) {
>   return cmp_impl<std::tuple<Args...>, 0>()(a, b);
> }
> }

Here's yet another offering, this one based on libc++'s implementation
of operator< for tuples.
(I write __tuple_spaceship where libc++ has __tuple_less.)  I made
some things constexpr because "why not". Notice the overload for
std::string; it would be a good idea to add overloads for
LLVM-specific string types too.


namespace llvm {

  template <class _Tp, class _Up>
  constexpr int spaceship(const _Tp& __x, const _Up& __y)
  {
    return (__x < __y) ? -1 : (__y < __x) ? 1 : 0;
  }

  template <size_t _Ip>
  struct __tuple_spaceship
  {
    template <class _Tp, class _Up>
    constexpr int __step2(int __r, const _Tp& __x, const _Up& __y) const
    {
      // in C++14 this would just be the second line of operator()
      return (__r != 0) ? __r : spaceship(std::get<_Ip-1>(__x),
std::get<_Ip-1>(__y));  // ADL
    }

    template <class _Tp, class _Up>
    constexpr int operator()(const _Tp& __x, const _Up& __y) const
    {
      return __step2(__tuple_spaceship<_Ip-1>()(__x, __y), __x, __y);
    }
  };

  template <>
  struct __tuple_spaceship<0>
  {
    template <class _Tp, class _Up>
    constexpr int operator()(const _Tp&, const _Up&) const
    {
      return 0;
    }
  };

  template <class ..._Tp, class ..._Up>
  constexpr int spaceship(const std::tuple<_Tp...>& __x, const
std::tuple<_Up...>& __y)
  {
    return __tuple_spaceship<sizeof...(_Tp)>()(__x, __y);
  }

  template<class _Cp, class _Tp, class _Ap,
                      class _Up, class _Bp>
  int spaceship(const std::basic_string<_Cp,_Tp,_Ap>& __x,
                const std::basic_string<_Cp,_Up,_Bp>& __y)
  {
    int __r = __x.compare(0, __x.size(), __y.data(), __y.size());
    return (__r < 0) ? -1 : (__r > 0);
  }

} // namespace llvm




More information about the cfe-commits mailing list