【发布时间】:2017-03-03 15:17:54
【问题描述】:
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 ???
};
}
这是来自 C++14 标准 (ISO/IEC 14882:2014) 第 5.1.2 节第 12 段的示例,我通过两种方式对其进行了修改:
- 首先,函数
f()的两个版本都有一个int作为第一个参数,所以变量x在任何情况下不 odr-used。 - 其次,我删除(注释掉)了 lambda
g2中的 capture-default。
此代码是否符合标准? clang 和 gcc 都编译成功。但是,在原始示例中,lambda g2 有一个 capture-default ([=]),因此变量 x 被隐式捕获,因为存在依赖表达式(也因为它可能是 odr-used 在函数f() #2_original)。请注意,在标准的上述段落中,有两个条件可以隐式捕获变量 x(odr-use OR 依赖表达式)。现在,没有 capture-default 也没有 odr-use:
-
这不应该是编译时错误,因为存在依赖表达式并且没有 capture-default?也就是说,变量
x需要被捕获,但它不能被捕获(假设g2调用具有两种参数,即产生sizeof(a)=1和其他sizeof(a)>1)。 -
或者依赖表达式隐式捕获变量的条件是否仅在存在 capture-default 时适用?这意味着,如果没有 odr-use(即,在函数
f() #2中没有const int&),无论 capture-default。那么,依赖表达式的第二个条件不是没用吗?
这是 C++14 标准 (ISO/IEC 14882:2014),第 5.1.2 节,第 12 段(强调我的):
一个 lambda-expression 具有关联的 capture-default,它没有明确地捕获 this 或变量具有自动存储持续时间(这不包括任何已发现引用 init-capture 关联的非静态数据成员的 id-expression),据说 隐式捕获实体(即this或变量)如果复合语句:
- odr-使用 (3.2) 实体,或
- 在潜在求值表达式 (3.2) 中命名实体,其中封闭的完整表达式取决于在 lambda 表达式 的到达范围内声明的通用 lambda 参数。强>
注意:lambda g 不会捕获变量 x,因为它在 f(x) 中没有odr-used(请参阅 C++14 标准 (ISO/IEC 14882:2014),第 5.1.2 节,第 13 段)
链接:
【问题讨论】:
标签: c++ lambda c++14 auto one-definition-rule