Struct member equality without overloading operator== in C++

Question

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.


Show source
| generics   | c++   | templates   | struct   | equality   2017-01-06 05:01 3 Answers

Answers ( 3 )

  1. 2017-01-06 05:01

    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.

  2. 2017-01-06 05:01

    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.

  3. 2017-01-07 10:01

    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
    
◀ Go back