Search code examples
c++c++11gccgcc4.7

gcc 4.7.2 compile error on a lambda capturing this


I have kind of a weird issue and while trying to create a small example to post here on stackoverflow, I failed to reproduce. Hopefully, this will still ring a bell to somebody, or somebody has a good idea to dig further...

On my Mac, the below code compiles fine with gcc 4.9.2. I'm using g++ -std=c++11 test.cpp. On some other Linux/Fedora machine with gcc 4.7.2, I get a compilation error. Not on the below test example, but on a more complicated problem. I'm, however, not allowed to post that here, and unable to see what exactly is different.

I did, however, find a way to make it compile, by simply trying lots of things. I hope somebody might see what is wrong from that hint. The way I could get my program to compile was to change the lambda body from v.push_back... into this->v.push_back...

Any idea why that could be??

The compilation error I'm seeing is:

/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:881:7: note: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = aggregate; _Alloc = std::allocator<aggregate>; std::vector<_Tp, _Alloc>::value_type = aggregate] <near match>
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:881:7: note: no known conversion for implicit 'this' parameter from 'const std::vector<aggregate>*' to 'std::vector<aggregate>*'
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:899:7: note: void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = aggregate; _Alloc = std::allocator<aggregate>; std::vector<_Tp, _Alloc>::value_type = aggregate] <near match>
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:899:7: note: no known conversion for argument 1 from 'aggregate' to 'std::vector<aggregate>::value_type&& {aka aggregate&&}'

The following fails to compile on the Linux machine with gcc 4.7.2:

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

struct aggregate {
    int foo;
    char bar[2];
};

template<typename T>
class test {
private:
    std::vector<aggregate> v;
    std::function<void(aggregate&)> lambda;
public:
    test() :
        lambda([this] (aggregate& a) { v.push_back(a); })
    {
        v.reserve(8);
    }

    void execute() {
        aggregate a{1, "x"};
        lambda(a);
    }
};

int main() {
    test<int> t;
    t.execute();
}

$ g++ -std=c++11 test.cpp test.cpp
In lambda function:
test.cpp:17:53: error: no matching function for call to 'std::vector<aggregate>::push_back(aggregate&) const'
test.cpp:17:53: note: candidates are:
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/vector:65:0, from test.cpp:1:
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:881:7: note: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = aggregate; _Alloc = std::allocator<aggregate>; std::vector<_Tp, _Alloc>::value_type = aggregate] <near match>
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:881:7: note: no known conversion for implicit 'this' parameter from 'const std::vector<aggregate>*' to 'std::vector<aggregate>*'
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:899:7: note: void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = aggregate; _Alloc = std::allocator<aggregate>; std::vector<_Tp, _Alloc>::value_type = aggregate] <near match>
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:899:7: note: no known conversion for argument 1 from 'aggregate' to 'std::vector<aggregate>::value_type&& {aka aggregate&&}'

But works fine after changing v.push_back... into this->v.push_back...


Solution

  • Might the above be a manifestation of this bug in GCC 4.7.2?

    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54277

    Bug 54277 - [4.7/4.8 regression] Template class member referred to with implicit this inside lambda is incorrectly const-qualified

    This answer was reached in a comment thread and is being pulled up here for consideration as a possible answer. If nothing else, it's the closest I've found that explains what's going on and why this doesn't occur in the newer compilers.