带有std :: function的通用lambda不捕获变量 [英] Generic lambda with std::function does not capture variables
问题描述
我试图使用C ++ 14的通用lambda,但是遇到std :: function的麻烦。
I'm trying to use the generic lambda of C++14, but got a trouble with std::function.
#include <iostream>
#include <functional>
int main()
{
const int a = 2;
std::function<void(int)> f = [&](auto b) { std::cout << a << ", " << b << std::endl; };
f(3);
}
这无法编译时出现错误信息说错误:'a'未在此范围中声明
This fails to compile with an error message saying that error: ‘a’ was not declared in this scope
.
如果我将其更改为 )
。
这是一个错误?
推荐答案
我使用的GCC版本是4.9.2。解决方案
除非我执行以下任何操作,否则我可以重现此操作:
I can reproduce this unless I do any of the following:
- remove
const
来自a
- name
捕获列表
- 更改
std :: function< void(int)>
c $ c> auto - 通过将
auto b
更改为int b
- 使用Clang(例如v3.5.0)
- remove
const
froma
- name
a
in the capture-list - change
std::function<void(int)>
toauto
- make the lambda non-generic by changing
auto b
toint b
- use Clang (e.g. v3.5.0)
我相信这是一个与优化相关的编译器错误,并且无法在通用lambda中检测 odr-use (虽然有趣的是设置 -O0
没有效果)。它可能与错误61814 相关,但我不认为它相同,因此:
I believe that this is a compiler bug related to optimisations and a failure to detect odr-use in a generic lambda (though it's interesting that setting -O0
has no effect). It could be related to bug 61814 but I don't think it's quite the same thing, therefore:
我提出了 GCC错误64791 。
I have raised it as GCC bug 64791.
- (Update: this bug has since been marked as fixed in GCC 5.0.)
当然,我可以没有发现任何明显的C ++ 14措辞,应该禁止你的代码,虽然在新的C ++ 14的措辞一般很少明显。 :(
Certainly I can't find anything obvious in the C++14 wording that should disallow your code, though there's very little "obvious" in general in the new C++14 wording. :(
[C ++ 14:5.1.2 / 6]:
[..] 对于没有lambda捕获的通用lambda,closure类型有一个公共非虚拟非显式const转换函数模板到指针转换函数模板具有相同的发明的 template-parameter-list ,并且指向函数的指针具有与函数调用运算符模板相同的参数类型。 [..] / em>
[C++14: 5.1.2/6]:
[..] For a generic lambda with no lambda-capture, the closure type has a public non-virtual non-explicit const conversion function template to pointer to function. The conversion function template has the same invented template-parameter-list, and the pointer to function has the same parameter types, as the function call operator template. [..]
[C ++ 14:5.1.2 / 12]:
表达式与相关联的捕获默认不会显式捕获此或具有自动存储持续时间的变量(这排除了已找到的任何 id-expression 参见 init-capture 的关联非静态数据成员),被称为隐式捕获实体(即 this
)如果复合语句:
[C++14: 5.1.2/12]:
A lambda-expression with an associated capture-default that does not explicitly capture this or a variable with automatic storage duration (this excludes any id-expression that has been found to refer to an init-capture's associated non-static data member), is said to implicitly capture the entity (i.e., this
or a variable) if the compound-statement:
- odr-使用(3.2)实体,
- 将实体命名为潜在求值表达式(3.2),其中包含的full-expression取决于在lambda表达式范围内声明的通用lambda参数。 / li>
- odr-uses (3.2) the entity, or
- names the entity in a potentially-evaluated expression (3.2) where the enclosing full-expression depends on a generic lambda parameter declared within the reaching scope of the lambda-expression.
[示例:
void f(int, const int (&)[2] = {}) { } // #1
void f(const int&, const int (&)[1]) { } // #2
void test() {
const int x = 17;
auto g = [](auto a) {
f(x); // OK: calls #1, does not capture x
};
auto g2 = [=](auto a) {
int selector[sizeof(a) == 1 ? 1 : 2]{};
f(x, selector); // OK: is a dependent expression, so captures x
};
}
应在lambda表达式的到达范围内声明。 [注意:嵌套lambda表达式对实体的隐式捕获可能导致其通过包含lambda表达式的隐式捕获(见下文)。隐式的 odr-uses 可能会导致隐式捕获。 -end note]
—end example ] All such implicitly captured entities shall be declared within the reaching scope of the lambda expression. [ Note: The implicit capture of an entity by a nested lambda-expression can cause its implicit capture by the containing lambda-expression (see below). Implicit odr-uses of this can result in implicit capture. —end note ]
[C ++ 14:5.1.2 / 13]:
如果实体被显式或隐式捕获,则捕获它。在包含 lambda-expression 的范围内,使用由 lambda-expression 捕获的实体(3.2)。 [..]
[C++14: 5.1.2/13]:
An entity is captured if it is captured explicitly or implicitly. An entity captured by a lambda-expression is odr-used (3.2) in the scope containing the lambda-expression. [..]
这篇关于带有std :: function的通用lambda不捕获变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!