gez*_*eza 7 c++ language-lawyer c++17
该标准说明了dcl.constexpr/6中的模板constexpr函数/构造函数:
如果constexpr函数模板的实例化模板特化或类模板的成员函数无法满足constexpr函数或constexpr构造函数的要求,那么该特化仍然是constexpr函数或constexpr构造函数,即使调用这样的函数不能出现在常量表达式中.如果模板的特化不满足constexpr函数或constexpr构造函数在被视为非模板函数或构造函数时的要求,则模板格式错误,无需诊断.
有趣的是:
无法满足... constexpr构造函数的要求,该特化仍然是... constexpr构造函数
因此,即使构造函数被标记constexpr,也不能在常量表达式中使用它.
为什么存在这个规则?constexpr当功能不满足要求时,为什么不删除?
目前的行为在两个方面很糟糕:
constexpr默默地删除.constexpr构造函数),将动态初始化,没有任何错误/警告(因为构造函数不是"真正"constexpr).这条规则是否有一些优点,这可以平衡它的缺点?
此规则允许您编写模板化构造函数/函数,并将其标记为constexpr即使并非总是constexpr(至少有时).
例如,std::pair有constexpr构造函数,但它当然可以在常量表达式之外使用.
这是非常明智的,因为否则你将不得不复制所有这些函数(一次使用constexpr,一次不使用),即使代码完全相同.我们甚至不考虑歧义.
由于通常不可能证明模板不能满足constexpr,因此不需要诊断(但它是不正确的,因此如果他们能够针对给定的情况证明这一点,编译器可以向您抱怨).
你是正确的,如果你想指定"这个函数只能用于常量表达式" 这不是很有用,但这不是这个措辞的目标.
编辑:为了澄清,constexpr 对于函数而言,仅意味着"在常量表达式内进行合法评估"(此处更准确的措辞),而不是 "只能在编译时进行评估".相反,constexpr必须使用常量表达式初始化变量.
另一个编辑:感谢@JackAidley,我们有准确的措辞要讨论!
如果constexpr函数模板的实例化模板特化将无法满足constexpr函数的要求,
constexpr则忽略指定符并且特化不是constexpr函数.
这个问题是"至少有一组参数可以对函数进行常量评估"是"constexpr函数的要求"的一部分.因此,编译器无法实现此子句,因为不可能(通常)证明给定函数(或函数模板实例化)是否存在这样的集合.你要么必须进一步混淆这个要求,要么放弃这个方面.委员会似乎选择了后者.