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?
See @Shafik Yaghmour's answer for the full info.
The following paragraph forbids this for non-templates (7.1.5(3)):
To elaborate, a literal type is defined in 3.9(10) as a scalar type or a composition of literal type objects in an array or struct.
void
is not a scalar type by 3.9(9).Your function returns the value of
void()
, you are not returning from a void function per se. You are returning aNULL
value. What you are doing is equivalent to this:This returns a void value, the only void value. you can't return anything else from a void function because it will be of a different type.
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 wording is pretty similar pre C++11 as well.
This okay in a constexpr even though section
7.1.5
paragraph3
says:and includes this bullet:
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:As Casey noted in the C++14 draft standard void is a literal, this is section
3.9
Types paragraph 10 says:and includes: