问题
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
回答1:
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.
回答2:
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?
Because compiler think that you declare local variable with name item.
http://codepad.org/YBPKCvmm
回答3:
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:
There is an ambiguity in the grammar involving expression-statements and declarations: An expression-statement with a function-style explicit type conversion (5.2.3) as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a (. In those cases the statement is a declaration.
[...]
T(a); // declaration
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.
[...] the resolution is to consider any construct that could possibly be a declaration a declaration. (8.2)
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.
回答4:
"shadowing" means that two objects have the same name, which the language allows at this point, but might not be intended.
来源:https://stackoverflow.com/questions/5297763/gccs-two-unusual-error-messages