Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding the : in front of variable gives wrong result

Tags:

c++

c++11

std-tie

I am comparing the class. For the below code

#include <string>
#include <set>
#include <tuple>
#include <cassert>


enum class e : bool
{
    positive = true,
    negetive = false
};


class A
{
public:
    int a;
    e e1 : 1;
    
  friend bool operator==(const A&, const A&);
};

 
 bool operator==(const A& lhs, const A& rhs) {
  auto tie = [](const A& a1) {
    return std::tie(a1.a, a1.e1);
  };
  auto x1 = tie(lhs);
  auto x2 = tie(rhs);
  return x1 == x2;   
}

int main()
{
A a1;
a1.a = 10;
a1.e1 = e::positive;

A b1;
b1.a = 10;
b1.e1 = e::positive;

assert(a1 == b1);

}

Output is :

a.out: main.cpp:44: int main(): Assertion `a1 == b1' failed.

Which is wrong, as two of the classes are the same.

However, if I change the line of code from e e1 : 1; to e e1; it gives the right result.

First of I am wondering what does : does in this case? Why the result is wrong after adding this?

Code can be seen here.

Thanks in advance.

like image 791
Swapnil Avatar asked Mar 02 '23 01:03

Swapnil


1 Answers

This function:

auto tie = [](const A& a1) {
    return std::tie(a1.a, a1.e1);
};

returns a std::tuple<int const&, e const &>. Even though the fields that the tuple store are references, there is a special rule for bit fields where a temporary copy of the bit field is made, and a reference is bound to that temporary. This means when you return from the function, the reference to the bit field is dangling, leading to undefined behavior when you use that field of the tuple later.

You can fix this by explicitly specifying the return type:

auto tie = [](const A& a1) -> std::tuple<int, e> {
    return std::tie(a1.a, a1.e1);
};

Here's a demo.

Alternatively, you could return a tuple that decays the argument types, and avoids the dangling issue, like this:

auto tie = [](const A& a1) {
    return std::make_tuple(a1.a, a1.e1);
};
like image 86
cigien Avatar answered Mar 12 '23 18:03

cigien