gcc 4.7.2 在捕获这个的 lambda 上编译错误

gcc 4.7.2 compile error on a lambda capturing this

我遇到了一个奇怪的问题,在 Whosebug 上尝试为 post 创建一个小示例时,我未能重现。希望这仍然会给某些人敲响警钟,或者有人有进一步挖掘的好主意...

在我的 Mac 上,下面的代码可以用 gcc 4.9.2 正常编译。我正在使用 g++ -std=c++11 test.cpp。在其他一些装有 gcc 4.7.2 的 Linux/Fedora 机器上,我遇到编译错误。不是下面的测试示例,而是更复杂的问题。但是,我不允许 post 在这里,并且看不出到底有什么不同。

不过,我确实通过简单地尝试了很多东西,找到了一种编译它的方法。我希望有人能从这个提示中看出问题所在。 我可以让我的程序编译的方法是将 lambda 主体从 v.push_back... 更改为 this->v.push_back...

知道为什么会这样吗?

我看到的编译错误是:

/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&&}'

以下无法在 Linux 机器上用 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&&}'

但将 v.push_back... 更改为 this->v.push_back...

后工作正常

我敢打赌这是对 aggregate 的 RValue 引用。请注意它的类型是 aggregate&& 而不是 aggregate& 并且 gcc 4.7 不支持它。

https://gcc.gnu.org/gcc-4.7/cxx0x_status.html

 note: no known conversion for argument 1 from 
'aggregate' to 'std::vector::value_type&& {aka aggregate&&}'

以上可能是 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

这个答案是在评论线程中得出的,并被拉到这里以供考虑作为一个可能的答案。如果不出意外,这是我发现的最接近的解释发生了什么以及为什么在较新的编译器中不会发生这种情况。