Mehrwolf
Mehrwolf

Reputation: 8527

Compiler error in uninstantiated template when a constexpr function calls a non-constexpr one

In the following piece of C++11 code, the function get is constexpr but it tries to construct an instance via the non-constexpr constructor.

template <typename T>
struct S
{
    S() {}
    static constexpr S get() { return S(); }
};

int main()
{
    // S<int> s1;
    // auto s2 = s1.get();
}

While this code compiles with GCC, it fails with the compiler we use at work with the message

constexpr function return is non-constant.

We started a discussion whether the compiler is allowed to issue an error in this case. I think that the compiler has to accept the code. Otherwise I do not see how std::time_point could work in C++11 because its constructor is constexpr only since C++14.

So is this a quality-of-implementation thing or does the standard say something about uninstantiated templates w.r.t constexpr? Further, would it change anything if the code in the comments were activated (i.e. invoking a constexpr function on a non-constexpr object)?

Upvotes: 1

Views: 167

Answers (1)

Shafik Yaghmour
Shafik Yaghmour

Reputation: 158469

This line is fine:

S<int> s1;

but the following definition of get is ill-formed:

static constexpr S get() { return S(); }

since it does not return a literal type since S does not have a constexpr constructor.

From the draft C++11 standard section 7.1.5 The constexpr specifier [dcl.constexpr]:

The definition of a constexpr function shall satisfy the following constraints:

  • its return type shall be a literal type;

and later on the section it says (emphasis mine):

If the instantiated template specialization of a constexpr function template or member function of a class template would fail to satisfy the requirements for a constexpr function or constexpr constructor, that specialization is not a constexpr function or constexpr constructor. [ Note: If the function is a member function it will still be const as described below. —end note ] If no specialization of the template would yield a constexpr function or constexpr constructor, the program is ill-formed; no diagnostic required.

Note in the non-template case both gcc and clang generate an error since the return type is not a literal see it live.

Upvotes: 2

Related Questions