Объявление переменной с именем `this` внутри лямбды в скобках приводит к разным результатам на 3 разных компиляторах
В C++ можно объявить переменную в скобках, например int (x) = 0;
, Но похоже, что если вы используете this
вместо имени переменной используется конструктор: A (this);
звонки A::A(B*)
, Итак, первый вопрос, почему это отличается для this
потому что переменные не могут быть названы this
? И чтобы усложнить дело немного давайте this
внутри лямбда -
struct B;
struct A
{
A (B *) {}
};
struct B
{
B ()
{
[this] { A (this); } ();
}
};
Теперь gcc звонит A::A(B*)
, msvc выводит ошибку об отсутствующем конструкторе по умолчанию и печатает clang expected expression
( https://godbolt.org/g/Vxe0fF). Это даже смешнее в msvc - он действительно создает переменную с именем this
что вы можете использовать, так что это определенно ошибка ( https://godbolt.org/g/iQaaPH). Какой компилятор прав и каковы причины такого поведения?
1 ответ
В стандарте C++ §5.1.5 (статья 7 для C++11, статья 8 более поздний стандарт) [expr.prim.lambda]:
Составной оператор лямбда-выражения дает тело функции (8.4) оператора вызова функции, но для целей поиска имени (3.4), определения типа и значения этого (9.2.2.1) и преобразования выражений id со ссылкой на нестатические члены класса в выражениях доступа членов класса с использованием (*this) (9.2.2), составной оператор рассматривается в контексте лямбда-выражения. [ Пример:
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*
};
}
};
- конец примера]
Таким образом, GCC является правильным. Вы заметите, что их не исключение о том, что вы захватываете this
, Их точность, однако, с C++14 в случае, когда вы захватываете *this
до сих пор в §5.1.5 (статья 17):
Если * это захватывается копией, каждое использование этого odr преобразуется в указатель на соответствующий безымянный элемент данных типа замыкания, приводящий (5.4) к типу this.