我正在尝试使用
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)])
哪个是正确的?
我认为Clang是正确的
(使用当前 C++23 草案中的术语。)
std::size(arr1)
不是未求值操作数的一部分,因此表达式 arr1
是一个潜在求值的 id 表达式,命名变量 arr1
。该表达式也不是丢弃值表达式的一部分,变量 arr1
也不能用于常量表达式。因此,表达式 odr-使用 arr1
。 (该变量可以在常量表达式中使用,使 arr1
不是 odr-use,通过在其上添加 constexpr
。)
但是,作为一个具有自动存储持续时间的变量,
arr1
是一个局部实体,在表达式出现的范围内是不可使用的。具体来说,要在 lambda 内部可用,本地实体必须被 lambda 捕获,而 arr1
不是。然而,即使有捕获,CWG 2380 也澄清了本地实体仅在 lambda 的块范围内可用,而不是在函数参数声明子句中可用。
一个程序在一个范围内 ODR 使用本地实体,而在这个范围内它是不可用的。