Right angle brackets and backwards compatibility

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).

Leave a Reply

Your email address will not be published.