Search code examples
c++c++11comparisonstd

std::tie for less comparison and char arrays


I've always known that to implement in a fast way a operator< for a class, the fastest way that always works is to use std::tie.

E.g.

struct TestInt
{
int a = 0;
int b = 0;
};

TestInt first;
TestInt second(first);

bool aLess = std::tie( first.a, first.b)
  < std::tie(second.a, second.b);
bool bLess = std::tie( first.a, first.b)
  > std::tie(second.a, second.b);
EXPECT_EQ(aLess, false);
EXPECT_EQ(bLess, false);
EXPECT_EQ(aLess, bLess);

The same does not work if you use another struct containing members with array of chars like:

struct TieTestChar
  {
  char a[10];
  int b=0;
  TieTestChar() {strcpy(a, "test");}
  };

TieTestChar first;
TieTestChar second(first);

bool aLess = std::tie( first.a, first.b)
  < std::tie(second.a, second.b);
bool bLess = std::tie( first.a, first.b)
  > std::tie(second.a, second.b);
EXPECT_EQ(aLess, false);
EXPECT_EQ(bLess, false);
EXPECT_EQ(aLess, bLess);

What am I missing?

[test case edited]


Solution

  • You might mimic std::tie with special case for C-arrays, something along

    template <typename T>
    struct my_ref
    {
        using type = T&;
    };
    
    template <typename T, std::size_t N>
    struct my_ref<T[N]>
    {
        using type = my_span<T/*, N*/>; // std::span doesn't provide comparison operators
    };
    
    template <typename T>
    using my_ref_t = typename my_ref<T>::type;
    
    template <typename ... Ts>
    std::tuple<my_ref_t<Ts>...> my_tie(const Ts&... args) { return {args...}; }