以下のコードはwell-formedなC++0xのコードである。ただし、C++03ではill-formedである。
class Y ; class X { friend Y ; } ;
MSVCでコンパイルが通り、GCCでコンパイルが通らなかったので、てっきりまた、MSVCのバグかと思ったが、規格を参照したところ、MSVCの実装はC++0xとして正しいものであった。あやうくMSVCにバグ報告するところであった。危ない危ない。もちろん、ただしくGCCの方にバグ報告しておいた。
追記:バグではなく、未実装なのだという。まさかこのページのExtended friend declarationsがこれを意味するとは思わなかった。また、MSVCも、C++0xを実装しているというより、独自仕様である。C++0xの規定するfriend宣言をすべて実装しているわけではない。
C++0xでは、type specifierがクラスの型を表す場合、friendクラスの宣言として扱われる。C++03では、friendクラスの宣言は、常にelaborated-type-specifierを使わなければならなかった。つまり、class-keyが必須だったのである。
// C++03対応版 class X { friend class Y ; } ;
もちろん、あらかじめ名前が宣言されていない場合は、C++0xでもエラーになる。
class X { friend Y ; // エラー、Yは宣言されていない friend class Y ; // OK } ;
ちなみに、type specifierがclass typeではない場合、無視される。これはどういう事かというと、例えば以下のようなコードが通るということだ。
template < typename T > class X { friend T ; // C++03ではエラー } ; X<int> x ; // friend宣言は無視される
この場合、friend宣言は、friend int ; という、意味のないものになってしまう。幸いにして、C++0xでは、単に無視される。その結果、コンパイルが通る。これにより、テンプレートコードが書きやすくなる。
コメントにも書いたように、C++0xでは、friendにtemplate parameterを使えるようになったが、それは、このブログの読者ならば、すでにご存知だろう。
No comments:
Post a Comment