Search code examples
c++templatesc++11returnvoid

Returning a void?


I do not understand why this code compiles without error:

#include <iostream>

template <class T>
struct Test
{
    static constexpr T f() {return T();} 
};

int main()
{
    Test<void> test;
    test.f(); // Why not an error?
    return 0;
}

Is it ok according to the standard, or is it a compiler tolerance?


Solution

  • This looks valid by the draft C++11 standard, if we look at section 5.2.3 Explicit type conversion (functional notation) paragraph 2 says (emphasis mine):

    The expression T(), where T is a simple-type-specifier or typename-specifier for a non-array complete object type or the (possibly cv-qualified) void type, creates a prvalue of the specified type, whose value is that produced by value-initializing (8.5) an object of type T; no initialization is done for the void() case.[...]

    the wording is pretty similar pre C++11 as well.

    This okay in a constexpr even though section 7.1.5 paragraph 3 says:

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

    and includes this bullet:

    its return type shall be a literal type;

    and void is not a literal in C++11 as per section 3.9 paragraph 10, but if we then look at paragraph 6 it gives an exception that fits this case, it says:

    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.

    As Casey noted in the C++14 draft standard void is a literal, this is section 3.9 Types paragraph 10 says:

    A type is a literal type if it is:

    and includes:

    — void; or