29

I knew that if we don't put space after closing angle brackets in a variable declaration, C++ throws the following error.

‘>>’ should be ‘> >’ within a nested template argument list

But the error doesn't come if I use #define like in this code. Can someone explain me this?

I think #define is just a macro expansion and works like find-replace, so both the ways of declaring variable here should be identical.

Also this error doesn't occur if I compile it with C++11.

#include <bits/stdc++.h> using namespace std; #define vi vector<int> int main(){ //Doesn't work, compile error vector<vector<int>> v; //Works vector<vi> vv; } 
11
  • 15
    In C++11 >> became valid, via a special rule, because the space requirement was such an annoyance. Commented Feb 17, 2015 at 10:02
  • 3
    If you run cpp over the file, you can see that a space is added between the two > characters. Commented Feb 17, 2015 at 10:06
  • 6
    @MSalters It's not misleading, it's diagnostic. When an integrated preprocessor feeds tokens directly to translation phase 7, whitespace is not explicitly represented. But when asked to generate textual output, the preprocessor must insert whitespace when necessary to preserve token boundaries. Modern preprocessors will do this only when they have to. So, when you see whitespace in textual preprocessor output that wasn't there in the original, you can conclude there's some rule requiring the things on either side of it to remain distinct tokens. Commented Feb 17, 2015 at 14:35
  • 5
    @Jignesh It's a g++ implementation detail. There's no guarantee it will still be there or do the same thing in the future, and no other compiler has it. Commented Feb 17, 2015 at 15:49
  • 3
    @Jignesh For instance, if I try to compile your test program with clang instead of g++ I get an error message, test.cc:1:10: fatal error: 'bits/stdc++.h' file not found. Commented Feb 17, 2015 at 15:50

1 Answer 1

36

Macro expansion happens after tokenisation; it doesn't replace text, but sequences of tokens.

This means that, with the macro, the expansion of vi gives a > token, separate from the one following the macro invocation. In each case, tokenisation only finds a single > character, so that's the resulting token.

Without a macro, the "greedy" tokenisation rule meant that the two consecutive characters were treated as a single >> token, until C++11 added a special rule for this case.

Sign up to request clarification or add additional context in comments.

4 Comments

To see this more clearly, consider #define plusi +i. You can now write int i = 0; std::cout << +plusi. Predict what happens and then try.
@MSalters OTOH, anyone putting that into production needs to be sacked
This is a bit counterintuitive considering that there is a separate preprocessor program, cpp, that will output plain text. I would have assumed that explicitly preprocessing, then compiling afterwards, would be the same as letting the compiler itself do the preprocessing.
This experiment shows that the preprocessor is being pretty smart about it. When using cpp to preprocess the code, it does indeed produce vector<vector<int> > with that space included. In other contexts it does not include the space.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.