そーいやまともに追いかけてなかったんですが,結局右シフト演算子の問題は後方互換性が無い方の解決策で落ち着きそうなんでしょ〜か?
(以下は GCC 4.3.0 以降を利用することを前提としたコードです)
// test.cpp #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'; }
> g++ test.cpp > ./a.out 0 3 > g++ -std=c++0x test.cpp > ./a.out 0 0
まー,ぶっちゃけ個人的にはこの後方互換性なら失っても良いという気もするけれど,国際的な標準規格を持つ言語である以上,こういう瑣末でもおろそかにできにゃいんだろうにゃー.
そーいや文法的には
この場所にこれだけ書いとけば (別にシフト演算子のところとかには何も書かなくても) 必要十分なのなー.
14.2 Names of template specializations
3 After name lookup (3.4) finds that a name is a template-name, or that an operator-function-id refers to a set of overloaded
functions any member of which is a function template, if this is followed by a <, the < is always taken as the delimiter of
a template-argument-list and never as the less-than operator. 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, the first of which is taken as the end of the template-argument-list and completes
the template-id. (以下略)