Takatoshi Kondo
Takatoshi Kondo

Reputation: 3550

Can the keyword `this` be used in the class scope?

It seems that I can define lambda expressions that capture this in the class scope. As far as I read N4640 up to date working draft, I couldn't find the sentence that allows the behavior. I think that I'm missing something...

Here is an example:

#include <iostream>
#include <functional>

struct foo {
    std::function<void()> f1 = [this]{ ++i; };
    int i = 0;
};

int main() {
    foo a;
    foo const& cref = a;
    cref.f1();
    std::cout << a.i << std::endl;
}

Running demo. (g++ -std=c++11 pedantic) https://wandbox.org/permlink/HPzaOxbBkOQOmuS6

Updated

Thanks to @Brian and @cpplerner comments, I understand what my essential question is. That is "Is the keyword this allowed to use in the class scope? not only non-static member function scope." If it does, I can use this in the lambda expression capture list in the class scope. It's very clear.

It seems that this in the class scope regard as non-const pointer.

In order to solve my essential question, I read N4640 9.2.2.1 The this pointer [class.this]. It seems that it is allowed syntactically, but I couldn't find the semantic description. For non-static member functions, I found the semantic description at 9.2.2/3 and 9.2.2/4.

updated

I updated the title of the question to represent my essential question.

The original question title was Can lambda expression in the class scope capture this?

Upvotes: 6

Views: 214

Answers (1)

Takatoshi Kondo
Takatoshi Kondo

Reputation: 3550

Motivation to answer (by myself)

Thanks to the comments, my question is solved. I summarize the answer of the question using the comments for other people that see the question.

Can the keyword this be used in the class scope?

Yes. According to [expr.prim.this],

"The keyword this names a pointer to the object for which a non-static member function is invoked or a non-static data member's initializer ([class.mem]) is evaluated."

See @T.C 's comment.

Can the keyword this be written in the capture list of the lambda expression in the class scope?

No.

At least in the current draft of the C++ standard n4618, but C++ standard committee recognized as issue.

Here is the reason why this is NOT permitted.

According to expr.prim.lambda,

"A lambda-expression whose smallest enclosing scope is a block scope is a *local lambda expression; any other lambda-expression shall not have a capture-default or simple-capture in its lambda-introducer."

A lambda-expression in the class scope is NOT a local lambda expression. Because a class scope is not a block scope. Here is a definition of the word block.

So the lambda-expression in the class scple shall not have capture-default or simple-capture in its lambda-introducer.

The keyword this is one of simple-capture. See expr.prim.lambda.capture.

Hence, a lambda-expression that is in the class scope cannot capture this.

See this @cpplearner 's comment and @T.C 's comment.

Compiler implementation

I tested the following code on g++ and clang++.

#include <iostream>
#include <functional>

struct foo {
    std::function<void()> lambda_in_class_scope = [this]{
        std::cout << this << std::endl;
    };
};

int main() {
    foo f;
    std::cout << &f << std::endl;
    f.lambda_in_class_scope();
}

Output:

0x7fff8f409cb0
0x7fff8f409cb0

I got the same address. This indicates that this is captured correctly.

Here are running demos:

g++ 6.3 https://wandbox.org/permlink/FdhxJhVvripOQ1ng

clang++ 4.0 https://wandbox.org/permlink/kGoNBIoV5WTZV0sy

Upvotes: 1

Related Questions