I was recently asked by a student about a compile issue. The answer was quite simple but right now I am struggling about the reason. A simple example:
#include <iostream>
#include <vector>
struct MyStruct
{
typedef std::vector<int> MyIntVector;
MyIntVector CopyVector(MyIntVector const& vector);
};
MyStruct::MyIntVector MyStruct::CopyVector(MyIntVector const& vector)
^^^^^^^^
{
MyIntVector vec;
return vec;
}
int main(int /*argc*/, char** /*argv*/)
{
MyStruct st;
}
To be valid c++ code the return parameter has to be fully qualified. So much to the answer and to make the compiler/student happy.
But why has the return value to be qualified with the class and the parameter to the function not?
I always did this and I know that it has to do with the ADL lookup, but now that I was asked I searching for a better answer.
Can anyone give a me reference to the spec or a hint where I can find some more information?
The structure of the grammar is such that the return type is independant of what is declared and it is possible to declare (but not define) several things with the same type. This is valid C++:
int f(int), g(int);
so having the precise scope of the declared objects influencing the lookup for the type would be problematic. In
id1 ns1::f(int), ns2::g(int);
where would id1 be looked up?
One could have added special rules to use in function definition (there can be only one function definition -- so there would be no ambiguity --, but can be several object one), but I'm not sure the possibility has been examined, and I think the added complication would not be compensated by the advantage.
To proceed with parsing, the compiler needs to figure out what is a typename and what is not.
The only thing that can occur at namespace scope is a declaration, and most C++ declarations begin with a typename, but this is not the case in C. Putting a stray, undefined identifier at toplevel scope in a C program declares it to be an int
with static
visibility.
Regardless of the possibility of compiling a program, it also makes the parser much simpler if it can proceed from beginning to end without queuing up tokens for later identification within the context of the class.
C++11 solves the problem with trailing-return-type syntax:
auto MyStruct::CopyVector(MyIntVector const& vector) -> MyIntVector {
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