Skip to content

[QUESTION] How to properly capture this pointer in lambda #281

Closed
@filipsajdak

Description

@filipsajdak

In the current implementation of cppfront (4c52d2d) I am trying to capture this pointer to lambda:

html: namespace = {
    element: type = {
        children: html::children = ();
        parent: *element;

        set_parent:  (inout this, p : *element) = parent = p;

        operator=: (out this, forward cs : html::children) = {
            children = cs;
            parent = nullptr;
            for children do :(inout v) = {
                std::visit(:(inout c) = {
                    c.set_parent(this&$); // <-- trying to capture a pointer to this
                }, v);
            }
        }
    }
}

that produces (skipping boilerplate_:

for ( auto&& cpp2_range = children;  auto& v : cpp2_range ) {
    std::visit([_0 = (&(*this))](auto& c) -> void{
        CPP2_UFCS(set_parent, c, _0);
    }, v);
}

and fail to compile with an error:

[build] html/html.h2:115:31: error: 'this' cannot be implicitly captured in this context
[build]                     CPP2_UFCS(set_parent, c, _0);
[build]                               ^
[build] html/html.h2:115:21: note: explicitly capture 'this'
[build]                     CPP2_UFCS(set_parent, c, _0);
[build]                     ^

When capturing value before lambda creation like the following:

self := this&;
for children do :(inout v) = {
    std::visit(:(inout c) = {
        c.set_parent(self$);
    }, v);
}

Generates:

auto self {&(*this)}; 
for ( auto&& cpp2_range = children;  auto& v : cpp2_range ) {
    std::visit([_0 = self](auto& c) -> void{
        CPP2_UFCS(set_parent, c, _0);
    }, v);
}

That also ends with an error:

[build] html/html.h2:115:31: error: 'this' cannot be implicitly captured in this context
[build]                     CPP2_UFCS(set_parent, c, _0);
[build]                               ^
[build] html/html.h2:115:21: note: explicitly capture 'this'
[build]                     CPP2_UFCS(set_parent, c, _0);
[build]                     ^

When trying another syntax:

for children do :(inout v) = {
    std::visit(:(inout c) = {
        c.set_parent(this$&);
    }, v);
}

That worked and produced:

for ( auto&& cpp2_range = children;  auto& v : cpp2_range ) {
    std::visit([_0 = (*this)](auto& c) -> void{
        CPP2_UFCS(set_parent, c, &_0);
    }, v);
}

Unfortunately, this solution makes a copy of *this and calls set_parent with the address to the copy.

Question

Could you tell me how to capture a pointer to this in lambda?

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions