GCC的两个异常错误信息
今天,我遇到了两条以前从未见过的错误消息。这对我来说是全新的。
代码如下:
template<typename T>
struct adder { adder(const T &item) { } };
template<typename T>
void initializer(const T &item) { adder<T>(item); }
int main()
{
initializer("const string literal");
}
编译时,GCC 给出以下错误:
prog.cpp:在函数“voidinitializer(const T&)”中:
prog.cpp:6: 错误:'adder的声明item' 隐藏参数
prog.cpp:在函数“voidinitializer(const T&) [with T = char [21]]”中:
prog.cpp:10:从这里实例化
prog.cpp:6: 错误:'adder的声明item' 隐藏参数
prog.cpp:6: 错误:没有匹配的函数可用于调用 'adder::adder()'
prog.cpp:3:注意:候选者为:adder::adder(const T&) [with T = char [21]]
prog.cpp:3: 注意:adder::adder(const adder &)
请参阅粗体文本。一个错误显示两次,就是这个
错误:声明“adder
” item ' 隐藏参数
错误:声明 'adder; item ' 隐藏参数
是什么意思?为什么它使用不同的模板参数显示两次?第一个带有 T
,第二个带有 char [21]
?
编辑:adder
是否声明名为 item 的变量?但这不是我的本意。我认为它应该创建一个临时对象,将 item 作为参数传递给构造函数。
我想知道标准中处理此问题的部分!
其他有趣的错误是:
错误:没有匹配的函数可用于调用“adder
::adder()”
这表明编译器正在寻找默认构造函数?但我想知道为什么编译器要寻找它,而事实上我的代码在第 6 行并没有使用它?
ideone 上的代码: http://www.ideone.com/jrdLL
Today, I came across two error messages which I never seen before. It's completely new to me.
Here is the code:
template<typename T>
struct adder { adder(const T &item) { } };
template<typename T>
void initializer(const T &item) { adder<T>(item); }
int main()
{
initializer("const string literal");
}
On compiling, GCC gives these errors:
prog.cpp: In function ‘void initializer(const T&)’:
prog.cpp:6: error: declaration of ‘adder<T> item’ shadows a parameter
prog.cpp: In function ‘void initializer(const T&) [with T = char [21]]’:
prog.cpp:10: instantiated from here
prog.cpp:6: error: declaration of ‘adder<char [21]> item’ shadows a parameter
prog.cpp:6: error: no matching function for call to ‘adder<char [21]>::adder()’
prog.cpp:3: note: candidates are: adder<T>::adder(const T&) [with T = char [21]]
prog.cpp:3: note: adder<char [21]>::adder(const adder<char [21]>&)
See the bold text. One error is shown twice, which is this
error: declaration of ‘adder<T> item’ shadows a parameter
error: declaration of ‘adder<char [21]> item’ shadows a parameter
What does it mean? Why does it show twice with different template arguments? First one with T
, second one with char [21]
?
EDIT: does adder<T>(item)
declare variable with name item? But that is not what I intended. I think it should create a temporary object passing item as argument to the constructor.
I would like to know the section from the Standard which deals with this issue!
Other interesting error is this:
error: no matching function for call to ‘adder<char [21]>::adder()’
Which indicates that the compiler is looking for default constructor? But I'm wondering why is the compiler looking for it when in fact my code doesn't use it at line 6?
Code at ideone : http://www.ideone.com/jrdLL
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
理解正在发生的事情的关键是要认识到:
加法器(项目);
是一个名为 item 且具有类型的局部变量的定义
加法器;括号是多余的,但完美
允许的。如果你想调用构造函数,你将有
通过以某种不可能的方式书写来消除歧义
解释为数据定义,例如:
加法器((项目));
(我不确定这有什么用。它构造了一个临时的
adder 的对象,然后在末尾销毁它
表达式。)
一旦语句出现,实际的错误消息应该是清楚的(呃)
可以理解为数据声明:函数参数是
视为它们是在顶级块中定义的
函数,所以 adder(item) 是重复的(并且矛盾的)
定义,并且 adder 没有默认构造函数,所以
如果不提供参数就无法定义它的实例。
The key to understanding what is happening is to realize that:
adder(item);
is a definition of a local variable named item and having type
adder; the parentheses are superfluous, but perfectly
permissable. If you want to call the constructor, you'll have
to disambiguate, by writing it in some way that cannot be
interpreted as a data definition, say:
adder((item));
(I'm not sure what use this may be. It constructs a temporary
object of adder, then destructs it at the end of the
expression.)
The actual error messages should be clear(er) once the statement
is understood as a data declaration: function parameters are
treated as if they were defined in the top level block of the
function, so adder(item) is a duplicate (and contradictory)
definition, and adder doesn't have a default constructor, so
you can't define an instance of it without providing arguments.
我目前只能访问 C++0x 草案,因此我无法向您提供当前的章节和诗句,但我认为没有太大变化。
在 0x 中,它位于第 6.8 节 - 歧义解决:
[...]
也就是说,一个名为“a”、类型为 T 的变量的声明。
如果您的
adder(item)
要定义一个临时(未命名)对象,那么它将是一个表达式语句,但如果某些内容可以被解析为声明语句或表达式语句,则 C++ 会将其解析为声明语句。换句话说,它是每个人亲爱的老朋友“最令人烦恼的解析”的表弟。
更新:
我查看了 C++03 中的歧义解决,这些段落是相同的。
I only have access to the C++0x draft at the moment, so I can't give you the current chapter and verse, but I don't think much has changed.
In 0x it's in section 6.8 - Ambiguity Resolution:
[...]
That is, a declaration of a variable named "a" of type T.
If your
adder<T>(item)
were to define a temporary (un-named) object, it would be an expression-statement, but if something can be parsed as either a declaration-statement or an expression-statement, C++ parses it as a declaration-statement.In other words, it's a cousin to everyone's dear old friend, the Most Vexing Parse.
Update:
I looked at ambiguity resolution in C++03, and those passages are identical.
“遮蔽”意味着两个对象具有相同的名称,语言目前允许这样做,但可能不是有意的。
"shadowing" means that two objects have the same name, which the language allows at this point, but might not be intended.
因为编译器认为您用名称 item 声明了局部变量。
http://codepad.org/YBPKCvmm
Because compiler think that you declare local variable with name item.
http://codepad.org/YBPKCvmm