Domanda

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 clang

However 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 clang

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

È stato utile?

Soluzione

[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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top