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.

5
  • 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. Commented Jan 6, 2017 at 4:25
  • 1
    stackoverflow.com/questions/5740310/… Commented Jan 6, 2017 at 4:26
  • This was discussed for C++17 but voted out again in the end if I'm informed correctly. Commented Jan 6, 2017 at 4: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... Commented Jan 6, 2017 at 4:33
  • Maybe this will help stackoverflow.com/q/217911/4224575 Commented Jan 6, 2017 at 15:44

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

6 Comments

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.
If the T has padding, such as struct {char a; int b;};, then there is no guarantee that it will work.
What do you mean by both cases? Two instance of the struct?
My question was about doing the memcpy but directly in a templated function template<T>AreEqual(const T&, const T&) instead of defining a ComparableStruct<T>.
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!
|
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

Comments

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.

1 Comment

I used templates in the example code to imply it should work for all structs

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.