类模板中的Constexpr成员函数

时间:2017-09-08 15:09:26

标签: c++11 templates constexpr

以下代码无法编译:

// 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 在类模板中有什么特殊含义吗?

据我了解,此代码不正确,但标准不要求编译器产生错误(为什么?)。

1 个答案:

答案 0 :(得分:3)

Per [dcl.constexpr]

  

constexpr函数的定义应满足以下约束条件:
  ...
初始化返回值(6.6.3,8.5)时使用的每个构造函数调用和隐式转换都应该是   其中一个允许持续表达

在常量表达式中不允许调用g()。 Per [expr.const]:

  

条件表达式核心常量表达式,除非它涉及以下之一作为潜在的   评估子表达式...:
   - 调用除constexpr函数

之外的函数

看起来某些编译器可能允许您执行您正在执行的操作,因为z未声明为constexpr,因此在编译时不需要知道该值。如果您将代码更改为

constexpr auto z = s.f();

你会注意到所有这些编译器都会进入barf,模板或者不是。