类模板中的Constexpr成员函数 [英] Constexpr member function in class template
问题描述
以下代码无法编译:
// 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,例如,抱怨: error:call to non- constexpr函数'int S :: g()const'。这是完全合理的。但是,如果我将 S 转换为模板,则会编译代码(使用MSVC 15.3,GCC 7.1.0,clang 4.0.1检查)。
GCC, for example, complains: error: call to non-constexpr function ‘int S::g() const’. This is perfectly reasonable. But if I turn S into a template, the code compiles (checked with MSVC 15.3, GCC 7.1.0, clang 4.0.1).
为什么? constexpr 在类模板中是否有任何特殊含义?
Why? Does constexpr has any special meaning in class templates?
据我了解,此代码是错误的,但该标准不需要编译器会产生错误(为什么?)。
As far as I understand it, this code is incorrect, but the standard does not require that compilers produce an error (why?).
推荐答案
每[dcl.constexpr]
Per [dcl.constexpr]
constexpr函数的定义应满足以下约束:
...
初始化构造函数时使用的每个构造函数调用和隐式转换返回值(6.6.3,8.5)应该是
常量表达式中允许的值之一。
The definition of a constexpr function shall satisfy the following constraints:
...
every constructor call and implicit conversion used in initializing the return value (6.6.3, 8.5) shall be one of those allowed in a constant expression
对<常量表达式中不允许code> g()。每个[expr.const]:
A call to g()
is not allowed in a constant expression. Per [expr.const]:
一个条件表达式是一个核心常量表达式,除非它涉及以下其中之一作为可能的
评估的子表达式...:
—调用[...] a以外的函数constexpr
函数
A conditional-expression is a core constant expression unless it involves one of the following as a potentially evaluated subexpression...:
— an invocation of a function other than [...] aconstexpr
function
看起来有些编译器可能允许您做您正在做的事情,因为 z
没有声明为 constexpr
,因此在编译时无需知道该值。如果将代码更改为
It looks like some compilers may allow you to do what you're doing because z
isn't declared constexpr
so the value doesn't need to be known at compile-time. If you change your code to
constexpr auto z = s.f();
您会注意到,所有这些编译器都将继续进行barf,模版转换。
you'll note that all those compilers will proceed to barf, template or not.
这篇关于类模板中的Constexpr成员函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!