使用lambda中捕获的const值作为模板参数是否合法?

Bri*_*ian 15 c++ lambda templates language-lawyer

请考虑以下代码,由同事提供:

#include <array>
#include <string>

int main() {
    const int size = 4;
    return [size]() {
      std::array<std::string, size> a; // *
      return a.size();
    }();
}
Run Code Online (Sandbox Code Playgroud)

它已被Clang 5.0.0接受但被GCC 7.2拒绝,并且主题行的错误消息为:

error: '__closure' is not a constant expression
Run Code Online (Sandbox Code Playgroud)

哪个编译器是对的?

Col*_*mbo 7

该规则实际上是直观的:任何不需要捕获的变量的出现都是指原始变量.[expr.prim.lambda]/11:

lambda 表达式复合语句中的 每个id表达式都是由副本捕获的实体的odr使用转换为对闭包类型的相应未命名数据成员的访问.[注意:不是odr-use id表达式是指原始实体,永远不是闭包类型的成员.[...] - 结束说明]

显然,声明的size变量可以用在常量表达式中,因此Clang是正确的.