Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Declaring variable with name `this` inside lambda inside parentheses leads to different results on 3 different compilers

In C++ it's possible to declare variable inside parentheses like int (x) = 0;. But it seems that if you use this instead of variable name, then constructor is used instead: A (this); calls A::A(B*). So the first question is why it's different for this, is it because variables can't be named this? And to complicate matters a bit lets put this inside a lambda -

struct B;
struct A
{
  A (B *) {}
};

struct B 
{
  B ()
  {
    [this] { A (this); } ();
  }
};

Now gcc calls A::A(B*), msvc prints error about missing default constructor and clang prints expected expression (https://godbolt.org/g/Vxe0fF). It's even funnier in msvc - it really creates variable with name this that you can use, so it's definitely a bug (https://godbolt.org/g/iQaaPH). Which compiler is right and what are the reasons for such behavior?

like image 411
Alex Telishev Avatar asked Mar 01 '17 10:03

Alex Telishev


1 Answers

In the C++ standard §5.1.5 (article 7 for C++11, article 8 later standard) [expr.prim.lambda]:

The lambda-expression’s compound-statement yields the function-body (8.4) of the function call operator, but for purposes of name lookup (3.4), determining the type and value of this (9.2.2.1) and transforming id- expressions referring to non-static class members into class member access expressions using (*this) (9.2.2), the compound-statement is considered in the context of the lambda-expression. [ Example:

struct S1 {
  int x, y;
  int operator()(int);
  void f() {
    [=]()->int {
      return operator()(this->x + y); // equivalent to S1::operator()(this->x + (*this).y)
                                      // this has type S1*
               };
  }
};

— end example ]

Thus, gcc is right. You will notice that their is no exception about the fact that you are capturing this. Their is, however a precision since C++14 in the case where you capture *this, still in §5.1.5 (article 17):

If *this is captured by copy, each odr-use of this is transformed into a pointer to the corresponding unnamed data member of the closure type, cast (5.4) to the type of this.

like image 112
Oliv Avatar answered Nov 15 '22 04:11

Oliv