问询:Lambda无需捕获constexpr变量即可用于if constexpr的标准依据
关于C++ Lambda捕获与if constexpr的疑问
先看这段可正常编译的代码:
void f() { constexpr bool x{}; auto g = []{ if constexpr (x) { } }; g(); } int main () { f(); }
即使把lambda的捕获列表从[]改为[x]或[&x],代码依然能编译,但clangd会给出如下警告:
Lambda capture 'x' is not required to be captured for this use (fix available) [-Wunused-lambda-capture]
针对这个场景有两个疑问:
- 此场景下捕获
x是否仅为冗余操作? - 从C++标准的哪部分内容可以得知,上述场景中无需捕获
x即可使用?毕竟若在if constexpr前添加(void)x;语句,则必须捕获x(使用[x]或[&x])。
问题解答
捕获
x确实是冗余操作x是constexpr变量,在if constexpr的条件表达式中,编译器会在编译阶段直接求值这个常量,完全不需要在运行时访问x的存储位置。此时捕获x没有任何实际作用,属于多余的操作,所以clangd会提示未使用的lambda捕获警告。C++标准中的相关规则
C++标准规定,lambda表达式使用外部变量时通常需要捕获,但当变量在常量表达式语境中被使用,且该变量是constexpr(或constinit)类型,同时其使用不依赖于运行时存储时,不需要捕获。
if constexpr的条件表达式属于常量表达式语境,在这个语境中使用constexpr变量x时,编译器直接取用它的编译期常量值,不需要引用它的内存地址——这就满足了无需捕获的条件。
而当添加(void)x;语句时,这个操作是在运行时语境中使用x,此时需要访问x的实际存储,所以必须通过捕获让lambda能访问到该变量的内存,否则就会违反lambda的作用域访问规则。
内容的提问来源于stack exchange,提问作者Enlico
相关产品推荐
相关产品推荐

