C++中永远无法得到常量表达式的lambda能否作为constexpr函数?
结论
Clang的该行为属于符合C++标准的可接受行为,不是Bug。
相关标准规则梳理
Lambda隐式constexpr规则
lambda的operator()在未显式指定constexpr说明符时,只要其实现满足所有constexpr函数的要求,就会被隐式声明为constexpr。
constexpr函数的特殊要求
C++14起对constexpr函数有一项要求:
至少存在一组参数值,使得函数的调用可以成为核心常量表达式的被求值子表达式(对于构造函数,足以用于常量初始化即可)。违反该条不要求编译器给出诊断。
示例代码分析
你给出的示例代码如下:
auto l = []()->bool { throw 42; }; constexpr bool t() { return l(); }
这个无参lambda的operator()无论如何调用都会抛出异常,不存在任何能成为核心常量表达式子表达式的调用场景,违反了上述constexpr函数的要求。但因为标准明确规定这种违反不需要编译器做诊断,因此编译器可以自由选择两种处理策略:
- 策略1(GCC采用):编译期直接判定该lambda的
operator()不满足constexpr要求,将其视为非constexpr函数,在后续constexpr函数t()调用它时直接报错。 - 策略2(Clang采用):暂时将该lambda的
operator()标记为constexpr,直到它实际被用于常量求值上下文时再检查并报错。
两种策略都完全符合标准要求,属于标准允许的实现自由度范畴。
内容的提问来源于stack exchange,提问作者Fedor
相关产品推荐
相关产品推荐

