c++ lambda捕获中引用常量绑定(&& B):叮当声与愚者?

vlf7wbxs  于 2022-12-01  发布在  其他
关注(0)|答案(1)|浏览(130)

在下列程式码中:

int foo() {
  int a = 5;
  auto l = [&r = std::move(std::as_const(a))] { return r; };
  return l();  
}

clang编译正常
gcc产生错误。

error: cannot capture 'std::move<const int&>((* & std::as_const<int>(a)))' by reference

我需要社区的帮助来从C标准的Angular 讨论这个案例:在C20中谁是正确的以及为什么正确。
从[expr.prim.lambda.capture]中,我不清楚该子句是否:
不带省略号的init-capture的行为就像声明并显式捕获“auto init-capture”形式的变量一样
是否意味着clang是正确的?如果是,为什么删除as_const会使两者都出错?
code example on godbolt

zz2j4svz

zz2j4svz1#

这似乎是一个愚者bug。init-capture的行为应该像声明一个带有auto前缀的相应变量一样,然后捕获它(与标准中的引用完全相同):

auto &r = std::move(std::as_const(a));

这会将auto推导为const int,使得变量具有const int&类型,并且初始化将是合式的,因为初始化器是const int类型的右值,const左值引用可以直接绑定到该右值。
然而,std::move在这里没有任何作用,没有它的结果也是一样的。(const类型上的std::move基本上没有任何意义。)
如果没有as_const,则会失败,因为auto将被推导为int,因此变量的类型为int&。然后,您尝试从右值(std::move的结果)初始化它,这在初始化非const左值引用时是不允许的。

相关问题