Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to compare objects of POD types

Tags:

c++

This example :

#include <iostream>
#include <cstring>

struct A
{
    int  a;
    bool b;
};

bool foo( const A a1, const A a2 )
{
    return ( 0 == std::memcmp( &a1, &a2, sizeof( A ) ) );
}

int main()
{
    A a1 = A();
    a1.a = 5;a1.b = true;
    A a2 = A();
    a2.a = 5;a2.b = true;

    std::cout<<std::boolalpha << foo( a1, a2 ) << std::endl;
}

is going to produce false, because of padding.

I do not have access to the foo function, and I can not change the way the comparison is done.

Assuming a bool occupies 1 byte (that is true on my system), if I change the struct A to this :

struct A
{
  int a;
  bool b;
  char dummy[3];
};

then it works fine on my system (the output is true).

Is there anything else I could do to fix the above problem (get the true output)?

like image 852
BЈовић Avatar asked Jun 30 '11 08:06

BЈовић


People also ask

What are POD types?

A POD type is a C++ type that has an equivalent in C, and that uses the same rules as C uses for initialization, copying, layout, and addressing. As an example, the C declaration struct Fred x; does not initialize the members of the Fred variable x.

Is a struct a POD?

The struct MyStruct has no user-defined ctor, dtor, etc and hence is a POD.

What is a POD class?

Learning pods — also called “pandemic pods,” micro-schools or nano-schools — are small groups of students (typically three to 10 children) who learn together outside the classroom but still in person. Some pods are hiring tutors to teach a child's school curriculum; some pods are sharing teaching duties among parents.

What is POD programming?

In computer science and object-oriented programming, a passive data structure (PDS, also termed a plain old data structure, or plain old data, POD) is a term for a record, to contrast with objects.


2 Answers

The first one is not working because of padding in the struct. The padding is having different bit patterns for both objects.

If you use memset to set all the bits in the object before using it, then it will work:

A a1;
std::memset(&a1, 0, sizeof(A));
a1.a = 5;a1.b = true;

A a2;
std::memset(&a2, 0, sizeof(A));
a2.a = 5;a2.b = true;

Online demos:

  • http://www.ideone.com/mVmsn (Original code written by you)
  • http://www.ideone.com/Q13QO (My modification)

By the way, you can write operator<, operator== etc, for PODs also.

like image 57
Nawaz Avatar answered Oct 24 '22 18:10

Nawaz


Since C++11 we can use tuples for simple POD comparison (tuples use lexicographical comparison for >, <, >= and <= operators, more info on that: https://en.cppreference.com/w/cpp/utility/tuple/operator_cmp ) :

#include <iostream>
#include <tuple>

struct Point {
    int x;
    int y;
    int z;    
};


auto pointToTuple(const Point& p) {
    return std::make_tuple(p.x, p.y, p.z);
}

bool operator==(const Point& lhs, const Point& rhs ) {
    return pointToTuple(lhs) == pointToTuple(rhs);
}

bool operator<(const Point& lhs, const Point& rhs ) {
    return pointToTuple(lhs) < pointToTuple(rhs);
}

int main()
{

    Point a{1, 2, 3};
    Point b{1, 2, 3};
    Point c{2, 2, 2};

    std::cout << (pointToTuple(a) == pointToTuple(b) ? "true" : "false") << "\n"; //true
    std::cout << (pointToTuple(a) == pointToTuple(c) ? "true" : "false") << "\n"; //false

    std::cout << (a == b ? "true" : "false") << "\n"; //true
    std::cout << (a == c ? "true" : "false") << "\n"; //false

    std::cout << (a < b ? "true" : "false") << "\n"; //false
    std::cout << (a < c ? "true" : "false") << "\n"; //true

}

C++20 should bring us default comparisons (https://en.cppreference.com/w/cpp/language/default_comparisons). So if class defines operator<=> as defaulted, compiler will automatically generate ==, !=, <, <=, > and >= operators and code for them:

struct Point {
    int x;
    int y;
    int z;    

    auto operator<=>(const Point&) const = default;
};
like image 36
Denis Sablukov Avatar answered Oct 24 '22 20:10

Denis Sablukov