7

Is it possible to define some kind of template that can create a generic comparable operator for structs?

For example is it possible for something like this?

struct A
{
    int one;
    int two;
    int three;
};
bool AreEqual()
{
    A a {1,2,3};
    A b {1,2,3};
    
    return ComparableStruct<A>(a) == ComparableStruct<A>(b);
}

All this does is a field by field comparison of the structs. You can assume all fields are of basic types or have overloaded operator==.

I have a lot of structs like this and it would save me a lot of time if I can just put it in a template or something for comparison rather than defining an operator== for every single struct. Thanks!

Update

It seems like this is not possible with C++. I wonder why this is voted out of C++ proposals, if anyone has the reasons let us know!

For solution that works with basic types only see solution by R Sahu.

Community
  • 1
  • 1
Nah
  • 331
  • 2
  • 9
  • I believe that you can't do that (and it is one of the limitations of C++14 metaprogramming machinery). But I don't know all of C++14. However `std::tuple` might be used instead. – Basile Starynkevitch Jan 06 '17 at 04:25
  • 1
    https://stackoverflow.com/questions/5740310/no-operator-found-while-comparing-structs-in-c – 5gon12eder Jan 06 '17 at 04:26
  • This was discussed for C++17 but voted out again in the end if I'm informed correctly. – 5gon12eder Jan 06 '17 at 04:28
  • That is a bit confusing though, since the compiler generates a default copy constructor, why doesn't it logically assume that the default `==` is such that `default-constructed-copy == original object`... – A.S.H Jan 06 '17 at 04:33
  • Maybe this will help http://stackoverflow.com/q/217911/4224575 – Lorah Attkins Jan 06 '17 at 15:44

3 Answers3

1

Is it possible to define some kind of template that can create a generic comparable operator for structs?

If the struct has no padding, you can use:

template <typename T>
struct ComparableStruct
{
   ComparableStruct(T const& a) : a_(a) {}
   bool operator==(ComparableStruct const& rhs) const
   {
      return (std::memcmp(reinterpret_cast<char const*>(&a_), reinterpret_cast<char const*>(&rhs.a_), sizeof(T)) == 0);
   }

   T const& a_;
};

Better yet, you can use a function template.

template <typename T>
bool AreEqual(T cost& a, T const& b)
{
   return (std::memcmp(reinterpret_cast<char const*>(&a), reinterpret_cast<char const*>(&b), sizeof(T)) == 0);
}

If the struct has any padding, there is no guarantee that use of std::memcmp will work to compare two objects.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • This is nice. Why would we not do this directly in a templated function such as `AreEqual`, since it is the final aim of the OP. If there is a specific reason I would like to know. – A.S.H Jan 06 '17 at 04:52
  • If the `T` has padding, such as `struct {char a; int b;};`, then there is no guarantee that it will work. – R Sahu Jan 06 '17 at 04:54
  • What do you mean by both cases? Two instance of the `struct`? – R Sahu Jan 06 '17 at 04:57
  • My question was about doing the `memcpy` but directly in a templated function `templateAreEqual(const T&, const T&)` instead of defining a `ComparableStruct`. – A.S.H Jan 06 '17 at 05:00
  • this is an interesting solution. This will only work for only basic types, or types that only allocates on the stack. Any types with operator== overloaded won't compare correctly. cool nonetheless! – Nah Jan 06 '17 at 07:17
  • @Nah, it will work for any POD types as long as there is no padding anywhere. – R Sahu Jan 06 '17 at 07:26
1

Look at https://github.com/apolukhin/magic_get. This library can automagically generate comparison operators for some fairly simple structs.

#include <iostream>
#include <boost/pfr/flat/global_ops.hpp>

struct S {
    char c;
    int i;
    double d;
};

int main() {
    S s1{'a', 1, 100.500};
    S s2 = s1;
    S s3{'a', 2, 100.500};

    std::cout << "s1 " << ((s1 == s2) ? "==" : "!=") << " s2\n";
    std::cout << "s1 " << ((s1 == s3) ? "==" : "!=") << " s3\n";
}

// Produces
// s1 == s2
// s1 != s3
Grisha
  • 526
  • 3
  • 10
0

What you asking to do is to traverse through various struct and comparing members is my understanding.

Iterating over a struct

This seems that it can't be done with standard c++, but that thread gives some ideas on what libraries to use.

It's not clear from your question if all the structs have the same format or not, and I'm assuming they do not.

Community
  • 1
  • 1