Ever since introduction of C++03 the standard committee set out to fix many minor annoyances in the language (auto, ranged for and initializer lists to name a few). Most of those are new things that cannot change the behaviour of existing code, but there are, of course, exceptions. In C++03 the first line of the following code was ill-formed, because >> was parsed as operator>>.
std::vector<std::vector<int>> X; // ill-formed std::vector<std::vector<int> > Y; // ok |
Most compilers already gave an error message about this, so it was proposed to make it a correct parse instead. Unfortunately, it wasn’t possible to fix this issue fully without breaking backwards compatibility in some regard. Consider the following code:
#include <iostream> template<int I> struct X { static int const c = 2; }; template<> struct X<0> { typedef int c; }; template<typename T> struct Y { static int const c = 3; }; static int const c = 4; int main() { std::cout << (Y<X<1> >::c >::c>::c) << '\n'; std::cout << (Y<X< 1>>::c >::c>::c) << '\n'; } |
It produces different results in C++03 and C++11, and, while it does look somewhat silly, some obscure uses of type traits might produce such code (imagine ::value instead of ::c).