タイトルに書いたようにこの問題、よその言語だとどうしているのかと気になったので、C#の場合を調べてみました。

「テンプレートの閉じ括弧が右シフト演算子に誤認される問題」と書きましたが、一般的にはなんと言えばよいのでしょうかね。コードを見れば分かると思います。これです。

1
2
3
4
5
6
7
#include <vector>
 
// C++03だとエラー、C++0xだとOK
std::vector<vector<int>> v1;
 
// C++03だと空白を入れねばならかった
std::vector<vector<int> > v2;

C++03では、前者が>>が1つのトークンとして解決されてしまうので、間に空白を入れて2つの>としなければならなかった問題です。

まず、C++0xでどういう風にOKとしたのかも知らないので、まずC++から見ました。現在最新のドラフトであるN3242 (PDF)の14.2 Names of tempalte specializationsの中に、次のような規定があります。

After name lookup (3.4) finds that a name is a template‐name or that an operator‐function‐id or a literaloperator‐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 >137 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.

こういうことですね。

  • テンプレート名の後の<は、演算子としてではなくテンプレート実引数並び (template‐argument‐list)との区切りとして扱う。
  • テンプレート実引数並びのあとの(入れ子になっていない)>は演算子としてではなく、テンプレート実引数並びを終わらせる区切りとして扱う。
  • テンプレート実引数並びのあとの(入れ子になっていない)>>は、トークン>が2つ並んだものとして扱う。うち1つ目はテンプレート実引数並びを終わらせる区切りとなるだろう。

もちろん、3つ目の決まりがC++0xで追加されたわけです。テンプレート実引数並びのあとの>>は>2つに分けるとしています。

続いてC#です。JIS X 3015:2008の9.4.5 演算子および区切り子から引用します。

《右シフト》::
> >
《右シフト代入》::
> >=

《右シフト》は,二つの字句>及び>から構成される。同様に,《右シフト代入》は,二つの字句>及び>=から構成される。これらの生成規則群においては、二つの字句の間には,構成文法における他の生成規則とは異なり,(空白類を含めた)任意の種類の文字を置くことは許されない。

なんと、C#にはそもそも>>というトークンがありませんでした。シフト演算子は>を2つ並べたものとした上で、間に他の文字を置くことを禁じて、「2 > > 1」のようなものがシフト演算子となることを防いでいるという具合です。

なお、ここには引用しませんでしたが、こういう規定になったのはジェネリックを導入したときからという注記があり、最初からこうだったわけではないようです。

C++は>>を必要に応じて>2つへ分解、C#は>2つを必要に応じて合体、全く異なるアプローチでした。本当は、まだまだほかの言語、Javaとかも見ればいいのでしょうが、とりあえずここまでとします。


スポンサード リンク

この記事のカテゴリ

  • ⇒ テンプレートの閉じ括弧が右シフト演算子に誤認される問題、ほかだとどうなの?
  • ⇒ テンプレートの閉じ括弧が右シフト演算子に誤認される問題、ほかだとどうなの?