Constexpr member function in class template

2019-06-24 07:21发布

问题:

The following code fails to compile:

// 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, 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).

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?).

回答1:

Per [dcl.constexpr]

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

A call to g() is not allowed in a constant expression. Per [expr.const]:

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 [...] a constexpr function

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();

you'll note that all those compilers will proceed to barf, template or not.