g++ 不允许在 lambda 中通过引用对 const 对象进行广义捕获?
Posted
技术标签:
【中文标题】g++ 不允许在 lambda 中通过引用对 const 对象进行广义捕获?【英文标题】:g++ won't allow generalized capture of const object by reference in lambda? 【发布时间】:2015-11-02 08:23:54 【问题描述】:这被 g++(4.9.3 和 5.2.0)拒绝,但被 clang 3.5.0 接受:
int main()
const int ci = 0;
auto lambda = [ &cap = ci ]() ;
g++ 给出error: binding ‘const int’ to reference of type ‘int&’ discards qualifiers
。似乎 g++ 拒绝允许捕获非常量引用,当然除了使用普通的旧 C++11 捕获 [&ci]
。这似乎是一个非常奇怪的约束,也许是 g++ 中的一个错误?
【问题讨论】:
***.com/questions/3772867/… @CoryKramer,这个问题确实密切相关。我今天也评论了这个问题。我想我的问题是:“给定一个 const 对象,我如何通过引用来捕获它?”。而这个问题是“给定一个 non-const 对象,我如何通过 const 引用捕获它?”。我想一个好的答案会涵盖这两个问题。 【参考方案1】:您的代码有效。 §5.1.2/11 去
init-capture 的行为就好像它声明并显式捕获了形式为 “
auto
init-capture;
的变量”,其声明区域是 lambda-expression 的 compound-statement […]
现在,明确地声明
auto &cap = ci;
捕获cap
很好。也就是说,
int main()
const int ci = 0;
auto &cap = ci;
auto lambda = [&cap]() ;
compiles with GCC。除了cap
的声明区域和生命周期之外,这个sn-p和你的没有区别,因此GCC是不正确的。
这个错误已经被报告为#66735,还有一个类似的例子:
int x = 0;
auto l = [&rx = static_cast<const int&>(x)] ;
【讨论】:
这样的话,我会尽快报告的。我非常惊讶以前没有注意到这个错误 - 它似乎是一个如此简单的例子。我肯定不是第一个尝试通过引用捕获 const 对象的人吗? @AaronMcDaid 你不是,但使用初始化捕获通过引用捕获const
对象可能很少发生。
This report 非常相似。我可能会用我稍微简单的例子来评论那个错误。
@AaronMcDaid 谢谢。我会将其纳入答案中。
我在尝试通过 const 捕获非 const 对象时发现了这一点,首先将其 const 转换为 const。但是,是的,捕获一个已经是 const 的对象(即我的问题)会很奇怪!【参考方案2】:
这看起来类似于gcc bug: [C++14] lambda init-capture fails for const references,它说:
这段代码编译失败:
int main() int x = 0; auto l = [&rx = static_cast<const int&>(x)]() ;
错误信息是:
test.cpp:3:14: 错误:将“const int”绑定到“int&”类型的引用 丢弃限定符
auto l = [&rx = static_cast<const int&>(x)]()
但是根据 [expr.prim.lambda]/11 rx 应该被捕获为 auto &rx = static_cast(x),即为 const int&。
错误报告引用 [expr.prim.lambda]/11 说:
init-capture 的行为就好像它声明并显式捕获了“auto init-capture ;”形式的变量 其声明区域是 lambda 表达式的复合语句,除了 [...]
【讨论】:
以上是关于g++ 不允许在 lambda 中通过引用对 const 对象进行广义捕获?的主要内容,如果未能解决你的问题,请参考以下文章