Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I compare 2 structures in C++?

Tags:

c++

structure

I have simply declared a structure like this -

struct data{
    int x,y;
};

Now I have declared 2 variables a & b of data type. I've assigned appropriate values to them. Now, I want to check if they are equal! I am trying to do like this -

data a,b;
a.x=12, a.y=24;
b.x=15, b.y=30;
if(a!=b)cout<<"a~b"<<endl;

But the compiler is giving me the following error on the 4th line ->

error: no match for 'operator!=' (operand types are 'data' and 'data')

Where is the problem actually? Isn't this compare supported in C++?? Or I'm making any mistakes??

What is the exact and easiest way to do this?? Do I need to compare each of the elements in the structure separately?? Or there's any other smarter way??

like image 666
jbsu32 Avatar asked Aug 10 '16 12:08

jbsu32


People also ask

Can we compare 2 structures in C?

C provides no language facilities to do this - you have to do it yourself and compare each structure member by member.

Why we Cannot compare structures in C?

Because the operator == is not aware of all the members of the structure it would need to compare, you are! You can't compare strings either, in C - at least, not with '==' or equivalent.

Can we compare two structures using any built in operator?

Yeah. It is relational operator. Relational operators are only used to compare two or more things.


2 Answers

C++ gives you attribute-by-attribute assignment implicitly, but no comparison for equality or ordering. The reason is "just because", don't look too hard into philosophy.

You must to provide those operators, if needed, by implementing them yourself explicitly, for example:

bool operator<(const Data& other) const {
    if (x < other.x) return true;
    if (x > other.x) return false;
    return y < other.y;
}

bool operator==(const Data& other) const {
    return x == other.x && y == other.y;
}

and so on.

Note also that defining for example == doesn't give you != automatically and defining < doesn't provide >= implicitly.

UPDATE

C++20 introduces (will introduce) a new operator <=> (friendly name "spaceship operator") exactly to remove the verbosity of having to define all possible relational operators. In this case adding:

std::strong_ordering operator<=>(const Data& other) const {
    if (auto cmp = x <=> other.x; cmp != 0) return cmp;
    return y <=> other.y;
}

will allow compilation of all relational tests (<, <=, >, >=, ==, !=) between elements of the class based on checking x first and, if that check doesn't resolve, checking y instead.

like image 160
6502 Avatar answered Sep 20 '22 14:09

6502


You have to implement all operators explicitely that you intent to use. In your case, you will need to supply bool operator!=(const data&, const data&).

A nice way to implement it for PODs like this is to use std::tuple since it already implements ordering:

#include <tuple>

// ...

bool operator!=(const data& p_lhs, const data& p_rhs)
{
    return std::tie(p_lhs.x, p_lhs.y) != std::tie(p_rhs.x, p_rhs.y);
}

std::tie (documentation) creates a temporary tuple of references. Those two tuples can then be compared, since std::tuple defines all comparison operators, as shown here.

I chose to implement operator!= as a free function. You can, of course, choose to implement it as member of your class:

struct data
{
    bool operator!=(const data& p_rhs) const
    {
        return std::tie(x, y) != std::tie(p_rhs.x, p_rhs.y);
    }

    int x, y;
};

Of course you should define all other operators, too. Remember that you can implement most operators by delegating to others.

like image 40
nshct Avatar answered Sep 18 '22 14:09

nshct