Issue
I have this piece of code with nested lambdas and both sort of capturing 'this':
class MyClass2 {
public:
int value;
MyClass2(int initialValue) : value(initialValue) {}
void executeLambda() {
auto outerLambda = [this]() {
value++;
auto innerLambda = [*this]() mutable {
value++;
};
innerLambda();
};
outerLambda();
}
};
cppinsights.io shows the compiler transformation as below:
class MyClass2 /* size: 4, align: 4 */
{
public:
int value; /* offset: 0, size: 4 */
inline MyClass2(int initialValue)
: value{initialValue}
{
}
inline void executeLambda()
{
class __lambda_10_28 /* size: 8, align: 8 */
{
public:
inline void operator()() const
{
__this->value++;
class __lambda_12_32 /* size: 4, align: 4 */
{
public:
inline /*constexpr */ void operator()()
{
(&__this)->value++;
}
private:
MyClass2 __this; /* offset: 0, size: 4 */
public:
__lambda_12_32(const MyClass2 & _this)
: __this{_this}
{}
};
__lambda_12_32 innerLambda = __lambda_12_32{*this}; // LINE_UNDER_CONSIDERATION
innerLambda.operator()();
}
private:
MyClass2 * __this; /* offset: 0, size: 8 */
public:
__lambda_10_28(MyClass2 * _this)
: __this{_this}
{}
};
__lambda_10_28 outerLambda = __lambda_10_28{this};
static_cast<const __lambda_10_28>(outerLambda).operator()();
}
// inline constexpr MyClass2(const MyClass2 &) noexcept = default;
};
Please refer to the line marked as "LINE_UNDER_CONSIDERATION".
*this
that refers to the class __lambda_10_28
is being passed to the constructor that is taking MyClass2
's object as an argument. How is that even correct? From the test case's point of view, it is correct that the constructor takes in the MyClass2
argument because we are capturing that only in the innerLambda
.
Seeing such a transformation of this piece of code, I'm curious as to how does GCC know that the this
that is getting passed is of the class MyClass2
and not the internally created lambda class?
Solution
This is a bug in cppinsight.
The line should be
__lambda_12_32 innerLambda = __lambda_12_32{*__this};
__this
is the this
pointer refering to the instance of MyClass2
passed when constructing the outer lambda.
Consider that the output cppinsight shows you is not actually exactly what gcc does internally. Neither is it proper C++ code. For example all identifiers used in the output are reserved for the implementation and if you use them in user code then your code invokes undefined behavior. The output of cppinsight is produced by cppinsight, it can give you a glimpse of what the compiler does internally, but it should be taken with a grain of salt. There can be bugs.
Answered By - 463035818_is_not_an_ai Answer Checked By - Robin (WPSolving Admin)