lambda 参数列表中的类型可以引用未捕获的外部变量吗?

问题描述 投票:0回答:1

我正在尝试使用

std::size
而不是像
_countof
ARRAYSIZE
这样的宏,但我遇到了范围界定问题。

下面的代码合法吗?

#include <iterator>

int main()
{
    int arr1[4];
    auto f = [](int(&arr2)[std::size(arr1)])
    {
        arr2[0] = 1;
    };
    (void)arr1;
    (void)f;
}

GCC 和 MSVC 编译得很好,但是 Clang 抱怨

error: variable 'arr1' cannot be implicitly captured in a lambda with no capture-default specified
    auto f = [](int(&arr2)[std::size(arr1)])

哪个是正确的?

c++ lambda c++17 constexpr scoping
1个回答
1
投票

我认为Clang是正确的

(使用当前 C++23 草案中的术语。)

std::size(arr1)
不是未求值操作数的一部分,因此表达式
arr1
是一个潜在求值的 id 表达式,命名变量
arr1
。该表达式也不是丢弃值表达式的一部分,变量
arr1
也不能用于常量表达式。因此,表达式 odr-使用
arr1
。 (该变量可以在常量表达式中使用,使
arr1
不是 odr-use,通过在其上添加
constexpr
。)

但是,作为一个具有自动存储持续时间的变量,

arr1
是一个局部实体,在表达式出现的范围内是不可使用的。具体来说,要在 lambda 内部可用,本地实体必须被 lambda 捕获,而
arr1
不是。然而,即使有捕获,CWG 2380 也澄清了本地实体仅在 lambda 的块范围内可用,而不是在函数参数声明子句中可用。

一个程序在一个范围内 ODR 使用本地实体,而在这个范围内它是不可用的。

© www.soinside.com 2019 - 2024. All rights reserved.