函数调用参数中的构造函数样式转换 [英] Constructor-style casting in function call parameters
问题描述
我不明白为什么使用构造函数转换时下面的代码无法编译:
template< typename T& ; void foo(const T& t){}
int main(){
foo(unsigned char(0));
}
错误是:
-
错误:gcc之前的未签名
之前的预期主表达式。 -
error:expected'('for function-style cast or type construction
for clang
这三个语法是正确的:
template< typename T> void foo(const T& t){}
int main(){
// c-style cast
foo((unsigned char)0);
//无符号
foo (0));
//别名unsigned char
typedef unsigned char uchar;
foo(uchar(0));
}
因此,类型中的空格显然是这里的怪。
我认为这可能与我们的老朋友最烦琐的解析有关,所以我尝试了统一初始化语法,这应该摆脱这种模糊,但没有运气:
template< typename T> void foo(const T& t){}
int main(){
foo(unsigned char {0});
}
但仍然:
-
错误:gcc之前的unsigned之前的预期主表达式
。 -
error:expected'('for function-style cast or type construction
for clang
问题是为什么不允许在函数式转换中包含一个空格的类型?它对我来说不够模糊。
注意:我知道我可以写 foo< unsigned char>(0)
,但它不回答问题;)
[C ++ 11:5.2.3 / 1] code> simple-type-specifier (7.1.6.2)或 typename-specifier (14.6)后跟括号 >构造给定表达式列表的指定类型的值。 [..]
检查语法,我们看到获得<$ c $
作为证据,可以从 simple-type-specifier 产品中选择
[C ++ 11:5.2.3 / 2]:
[..] 表10总结了简单类型说明符及其指定类型的有效组合。 (强调我)
允许在某些情况下:
[C ++ 11:7.1.6.2/ 3]:
当允许使用多个简单类型说明符时,它们可以以任何顺序与其他声明说明符自由混合。 [..]
…但没有迹象表明这是功能符号的情况,它清楚地说明 simple-type-specifier —
因此,GCC正确,Visual Studio错误。至于为什么这是case ...好吧,我不知道。我怀疑我们可以想出一些不明确的边缘情况,但是 Casey 在下面的评论中提出了一个好点,与函数调用语法不一致,因为函数名称中不能有空格。
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 ;)
[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.
这篇关于函数调用参数中的构造函数样式转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!