The reason you're not getting the error with the #define
method is that the preprocessor is intelligently inserting breaks. If you pass that code through only the preprocessor stage (gcc -E
, for example), you'll see something like:
int main() {
vector<int> v(10,-1);
vector<vector<int> > vv(10,v); // <<-- see space here.
for(int i=0; i<vv.size(); i++){
for(int j=0; j<vv[i].size(); j++){
cout << vv[i][j] << " ";
}
cout << endl;
}
return 0;
}
The reason why this happens has to do with the phases of translation as dictated by the ISO C++ standard.
Section 2.2 of C++11 (a) states that there are nine translation phases. Phase 3 is the splitting of the source file into preprocessing tokens and white space.
The important thing there is the tokenisation, so that vector<vi>
is the set of preprocessing tokens {vector, <, vi, >}
, it is not the simplistic text given in the macro replacement section. While a simplistic text substitution of:
#define vi vector<int>
#define vvi vector<vi>
vvi xyzzy;
would result in:
vector<vector<int>> xyzzy;
what you actually end up with is the preprocessing token set:
{vector, <, vector, <, int, >, >, WHITESPACE, xyzzy, ;}
Then, at phase 7, the standard states:
Each preprocessing token is converted into a token.
So, there's no recombining of the two >
tokens into a single one despite the fact a simple reading of the source may suggest that.
(a) Keep in mind that, though I'm quoting the C++11 parts of the standard to ensure the answer is more up-to-date, this particular problem is a C++03 one. C++11 actually fixes the parser so that multiple >
characters will close a template argument list where reasonable (C++03 always treated it as the right-shift operator).
C++11 14.2, section 3
specifies this:
When parsing a template-argument-list, the first non-nested >
is taken as the ending delimiter rather than a greater-than operator. Similarly, the first non-nested >>
is treated as two consecutive but distinct >
tokens ...