I don't understand why the following code fails to compile when using constructor-style casting:
template<typename T> void foo(const T& t){}
int main(){
foo(unsigned char(0));
}
The errors are:
error: expected primary-expression before ‘unsigned’
for gcc.error: expected '(' for function-style cast or type construction
for clangHowever these three syntaxes are correct:
template<typename T> void foo(const T& t){}
int main(){
// c-style cast
foo((unsigned char)0);
// without unsigned
foo(char(0));
// aliased unsigned char
typedef unsigned char uchar;
foo(uchar(0));
}
So the space in the type is obviously to blame here.
I thought it might be somehow related to our old friend the most vexing parse, so I tried the uniform initialization syntax, which is supposed to get rid of this sort of ambiguities, but no luck:
template<typename T> void foo(const T& t){}
int main(){
foo(unsigned char{0});
}
But still:
error: expected primary-expression before ‘unsigned’
for gcc.error: expected '(' for function-style cast or type construction
for clangSo my question is why is it not allowed to have a type containing a space in function-style casts? It doesn't look ambiguous to me.
note: I know I can write foo<unsigned char>(0)
, but it doesn't answer the question ;)
[C++11: 5.2.3/1]:
A simple-type-specifier (7.1.6.2) or typename-specifier (14.6) followed by a parenthesized expression-list constructs a value of the specified type given the expression list. [..]
Examining the grammar, we see that the only way to get unsigned char
from the simple-type-specifier production is by concatenating two of them.
As evidence debunking the rumour that table 10 is stating the contrary, which I may myself have started a short while ago (:P), the table heading says "specifier(s)" (note the optional plural), and refer to the below passage:
[C++11: 5.2.3/2]:
[..] Table 10 summarizes the valid combinations of simple-type-specifiers and the types they specify. (emphasis mine)
Now, combining simple-type-specifiers is allowed in some cases:
[C++11: 7.1.6.2/3]:
When multiple simple-type-specifiers are allowed, they can be freely intermixed with other decl-specifiers in any order. [..]
… but there's no indication that this is the case with functional notation, which clearly states "a simple-type-specifier" — singular.
Therefore GCC is correct, and Visual Studio is wrong.
As for why this is the case... well, I don't know. I suspect we could come up with some ambiguous edge case, but Casey makes a good point in the comments below that allowing this would be inconsistent with function call syntax, since names of functions cannot have spaces in them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With