将 lambda 中捕获的 const 值用作模板参数是不是合法?
Posted
技术标签:
【中文标题】将 lambda 中捕获的 const 值用作模板参数是不是合法?【英文标题】:Is it legal to use a const value captured in a lambda as a template argument?将 lambda 中捕获的 const 值用作模板参数是否合法? 【发布时间】:2018-04-04 16:02:28 【问题描述】:考虑以下由同事提供的代码:
#include <array>
#include <string>
int main()
const int size = 4;
return [size]()
std::array<std::string, size> a; // *
return a.size();
();
它被 Clang 5.0.0 接受,但被 GCC 7.2 拒绝,带星号的行的错误消息是:
error: '__closure' is not a constant expression
哪个编译器是正确的?
【问题讨论】:
用gcc 8编译。 我原以为它不应该编译,但闭包变成了一个难题中的一个谜。 如果我理解正确的话,CV 限定符会跟随副本捕获。因此,Clang 是正确的。 【参考方案1】:该规则实际上很直观:任何不需要捕获的变量都指的是原始变量。 [expr.prim.lambda]/11:
复合语句中的每个id-expression lambda-expression 是对通过副本捕获的实体的 odr 使用 转化为对相应未命名数据成员的访问 闭包类型。 [ 注意:一个 id-expression 不是 odr-use 指的是原始实体,绝不是闭包类型的成员。 […] — 尾注 ]
显然,声明的size
变量可以用在常量表达式中,因此Clang是对的。
【讨论】:
以上是关于将 lambda 中捕获的 const 值用作模板参数是不是合法?的主要内容,如果未能解决你的问题,请参考以下文章
这个 lambda 捕获参数中的 const-ness 是在哪里引入的?