Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is 'this' necessary despite capturing everything

Tags:

c++

c++14

Can anyone explain to me why I have to explicitly write "this->" in the second lambda even tho I captured everything ?

The error message for completeness:

cannot call member function 'result_t test::get()' without object

#include <iostream>
#include <functional>
#include <algorithm>
#include <vector>

using result_t = std::function<void()>;

struct test
{
    bool noMore = false;

    result_t get()
    {
        return [this]
        {
            std::vector<int> vec;
            vec.push_back(1);
            vec.push_back(2);
            vec.push_back(3);

            if(not noMore)
            {
                noMore = true;

                std::for_each(vec.begin(), vec.end(),
                    [&](const auto& i)
                    {
                        auto value1 = this->get(); // compiles
                        auto value2 = get(); // error
                    });
            }
        };
    }
};

int main() {
    test t;
    t.get()();
}

Godbolt

like image 228
user1233963 Avatar asked Apr 07 '16 14:04

user1233963


1 Answers

This is a gcc bug. From [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.3.2) and transforming id-expressions referring to non-static class members into class member access expressions using (*this) (9.3.1), 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 ]

In this case, get() should be equivalent to test::get(), and this is captured, so this is well-formed. clang compiles the code as-is. gcc compiles the code if you change i to be passed as an int instead of as const auto&, which is irrelevant to how get() is looked up.

like image 89
Barry Avatar answered Nov 03 '22 02:11

Barry