Jos*_*uis 6 c++ lambda one-definition-rule auto c++14
void f( int , const int (&)[2] = {}) { } // #1
void f( int , const int (&)[1] ) { } // #2
// void f(const int&, const int (&)[1] ) { } // #2_original
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 ???
};
}
Run Code Online (Sandbox Code Playgroud)
这是C++ 14标准(ISO/IEC 14882:2014),第5.1.2节,第12段中的一个例子,我用2种方式修改了它:
f()都有一个int作为第一个参数,因此变量在任何情况下x都不会 使用.g2.此代码是否符合标准?clang和gcc都编译成功.但是,在原始示例中,lambda g2具有capture-default([=]),因此x隐式捕获变量,因为存在依赖表达式(并且还因为它可能在函数中使用了odrf() #2_original).请注意,在标准的上述段落中,有两个条件隐式捕获变量x(使用odr的 OR依赖表达式).现在,没有capture-default或odr-use:
这不应该是一个编译时错误,因为有一个依赖表达式而没有capture-default?也就是说,x需要捕获变量,但它不能被捕获(假设g2使用两种参数调用,即产生sizeof(a)=1和其他参数sizeof(a)>1).
或者,当存在capture-default时,依赖表达式隐式捕获变量的条件是否仅适用?这意味着,没有odr-use(即,没有const int&函数f() #2),无论capture-default如何,程序都将以相同的方式工作.因此,关于依赖表达式的第二个条件不会无用吗?
这是C++ 14标准(ISO/IEC 14882:2014),第5.1.2节,第12段(强调我的):
具有关联的capture-default的lambda表达式 ,它不显式捕获此变量或具有自动存储持续时间的变量(这排除了任何已发现引用init-capture的关联非静态数据成员的id表达式) ,据说隐含地捕获实体(即,这个或变量),如果复合语句:
- odr-uses(3.2)实体,或
- 在潜在评估表达式(3.2)中命名实体,其中封闭的full-expression依赖于在lambda-expression的到达范围内声明的泛型lambda参数.
注意:lambda g不捕获变量,x因为它没有使用过f(x)(参见C++ 14标准(ISO/IEC 14882:2014),第5.1.2节,第13段)
链接:
该代码符合标准吗?
是的。规则是:
如果lambda 表达式或通用 lambda odr 的函数调用运算符模板的实例化使用 (3.2)
this或具有来自其到达范围的自动存储持续时间的变量,则该实体应由lambda 表达式捕获。
lambda odr-use 吗x?不,因为 [basic.def.odr]:
x名称显示为潜在求值表达式的变量ex将被odr 使用,ex除非应用左值到右值转换 (4.1) 生成x不调用任何非平凡函数的常量表达式 (5.20),并且 ifx是对象,ex是表达式 的潜在结果集的一个元素e,其中左值到右值转换(4.1)应用于e,或者e是一个丢弃值表达式(第 5 条)。
x是在应用左值到右值转换的表达式中使用的整型常量,因此不使用 odr。由于它不是 odr 使用的,因此您没有捕获它并不是一个错误。
如果存在f通过引用获取其第一个参数的重载,那么它将是格式错误的 - 调用运算符的实例化将是odr-use x,但它没有被捕获,从而使其格式错误。
您引用的部分与您修改后的示例无关。它仅指“具有关联捕获默认值的lambda 表达式 ”。但是你的 lambda 没有capture-default。捕获默认值是或,介绍人没有捕获默认值。但是,如果我们有或,该部分将解释为什么会被捕获。=&[][=][&]x