以下代码无法编译:
// template<class>
struct S {
int g() const {
return 0;
}
constexpr int f() const {
return g();
}
};
int main()
{
S /*<int>*/ s;
auto z = s.f();
}
例如,GCC抱怨:错误:调用非constexpr函数'int S :: g()const'。这是完全合理的。但是,如果我将 S 转换为模板,代码将编译(使用MSVC 15.3,GCC 7.1.0,clang 4.0.1进行检查)。
为什么呢? constexpr 在类模板中有什么特殊含义吗?
据我了解,此代码不正确,但标准不要求编译器产生错误(为什么?)。
答案 0 :(得分:3)
Per [dcl.constexpr]
constexpr函数的定义应满足以下约束条件:
...
初始化返回值(6.6.3,8.5)时使用的每个构造函数调用和隐式转换都应该是 其中一个允许持续表达
在常量表达式中不允许调用g()
。 Per [expr.const]:
条件表达式是核心常量表达式,除非它涉及以下之一作为潜在的 评估子表达式...:
之外的函数
- 调用除constexpr
函数
看起来某些编译器可能允许您执行您正在执行的操作,因为z
未声明为constexpr
,因此在编译时不需要知道该值。如果您将代码更改为
constexpr auto z = s.f();
你会注意到所有这些编译器都会进入barf,模板或者不是。