关于constexpr函数的标准指出[decl.constexpr]的第5点:
对于非模板,非默认constexpr函数或非模板,非默认,非继承constexpr构造函数,如果不存在任何参数值,则对该函数或构造函数的调用可以是如果评估核心常量表达式的子表达式(5.19),则程序格式不正确;无需诊断。
接着给出以下示例:
constexpr int f(bool b){ return b ? throw 0 : 0; } // OK
constexpr int f() { return f(true); } // ill-formed, no diagnostic required
我从中得出的结论是,带有空参数列表的函数是无法诊断的格式错误。这让我感到非常“奇怪”,以至于我怀疑我的理解是不正确的。例如,这是否也可能是错误的格式:
constexpr int g() { return 0; } // ill-formed?
如果是这样,其背后的原理是什么,如果不是,那么资格是什么意思/ constexpr函数何时会格式错误?
大概是可以的吗?
constexpr int h(int x) { return x; } // presumably fine?
constexpr int l = h(42); // also fine
答案 0 :(得分:6)
该规则的基本原理是应该至少存在一个 上下文,在该上下文中可以在constexpr
上下文中评估函数。例如给出:
constexpr int f(bool b){ return b ? throw 0 : 0; } // OK
constexpr int f() { return f(true); } // ill-formed, no diagnostic required
无法在f()
上下文中调用constexpr
,因为通过此函数的所有 all 路径将以不是 core常量的表达式结尾表达式。
编译器必须评估 all 个可能的调用,以查看该函数在constexpr
上下文中是否有任何可用的方法。通常,这不容易诊断,因此该语言表示这是 formed-no-diagnostic-required ,即您做错了什么,但编译器无法诊断。
请注意,如果f
的零参数重载如下:
constexpr int f() { return f(false); } // ok
那将是完美的,因为评估以 core-constant-expression 结尾。
类似地,此功能:
constexpr int g() { return 0; } // ok
以及这个:
constexpr int h(int x) { return x; } // ok
constexpr int l = h(42); // ok
很好,因为可以在g
上下文中调用h
和constexpr
。
“ ...的措辞,如果不存在参数值以致...” 可能会造成混淆,因为您曾问过g
的格式正确。但是g
可以用零个参数来调用,换句话说,可以用void
个参数来调用,所以很好。