该标准在 dcl.constexpr/6 中说明了模板 constexpr 函数/构造函数:
如果类模板的constexpr函数模板或成员函数的实例化模板专用化无法满足constexpr功能或constexpr构造函数的要求,则该专用化仍然是constexpr或constexprr构造函数,即使对此类函数的调用不能出现在常量表达式中。如果将模板视为非模板函数或构造函数时,模板的任何特殊化都不能满足constexpr函数或constexpr构造函数的要求,则模板格式不正确,不需要诊断。
有趣的部分是:
未能满足要求...Constexpr 构造函数,这种专业化仍然是一个...constexpr 构造函数
因此,即使构造函数用 constexpr
标记,也不能在常量表达式中使用。
为什么会存在此规则?当函数不满足要求时,为什么不删除constexpr
?
目前的行为在两个方面是不好的:
这条规则是否有一些优点,从而平衡了它的缺点?
此规则允许您编写模板化的构造函数/函数,并将其标记为<code>constexpr</code>,即使它不总是<code>constexpr<-code>(至少有时)。
例如,std::对
具有constexpr
构造函数,但它当然可以在常量表达式之外使用。
这是非常明智的,因为否则你将不得不复制所有这些函数(一次使用 constexpr
,一次不使用),即使代码完全相同。我们甚至不要考虑歧义。
由于通常不可能证明模板永远不能满足constexpr
,因此不需要对其进行诊断(但它的格式错误,因此编译器可以向您投诉,如果他们可以为给定案例证明这一点)。
你是对的,如果你想指定“这个函数只能在常量表达式中使用”,这不是很有用,但这不是这个措辞的目的。
编辑:为了澄清,<code>constexpr</code>for函数仅意味着“在常量表达式内求值合法”(此处更精确的措辞),而不是“只能在编译时求值”。相反,constexpr
变量必须用常量表达式初始化。
另一个编辑:我们有确切的措辞要讨论,感谢@JackAidley!
如果 constexpr 函数模板的实例化模板专用化无法满足 constexpr 函数的要求,则忽略 constexpr 说明符,并且专用化不是 constexpr
函数。
这样做的问题是“至少有一组参数可以对函数进行常量计算”是“constexpr函数的要求”的一部分。因此,编译器无法实现此子句,因为无法(通常)证明给定函数(或函数模板实例化)是否存在这样的集合。你要么必须进一步混淆这个要求,要么放弃这方面。委员会似乎选择了后者。