2006年01月31日

リファレンスへのリファレンス

C++ では「リファレンスへのリファレンス」や「リファレンスへのポインタ」は禁止されています。これを読んで「え? 出来るんですけど…」と思った方、おそらく以下のような例を考えているのではないでしょうか。

001 void f() {
002 // リファレンスへのリファレンス?
003 int i; // int を用意
004 int& ri = i; // それを参照するリファレンス
005 int& ri2 = ri; // そのリファレンスを参照するリファレンス
006
007 // リファレンスへのポインタ?
008 int* pi = &ri; // リファレンスのポインタ
009 }

確かに「リファレンスへのリファレンス」や「リファレンスへのポインタ」と言えなくもないですが、これは単にリファレンスやポインタをリファレンスによって初期化しているだけです。C++ で禁止されている「リファレンスへのリファレンス」や「リファレンスへのポインタ」は以下のようなものです。

001 void f() {
002 // リファレンスへのリファレンス
003 int i; // int を用意
004 int& ri = i; // それを参照するリファレンス
005 int&& ri2 = ri; // おっと、&& は論理AND演算子だ!
006 int& & ri3 = ri; // リファレンスへのリファレンス(エラー!)
007
008 // リファレンスへのポインタ
009 int&* pi = &ri; // リファレンスへのポインタ(エラー!)
010 }

リファレンスは参照先の別名に過ぎず、実体はありません。実体のないリファレンスを指し示すことは出来ませんし、実体のないリファレンスのアドレスが存在しないことも納得できます。

しかし、テンプレートとリファレンスを併用すると、簡単に「リファレンスへのリファレンス」が生成されてしまいます。
これは bind1st や bind2nd と mem_fun, mem_fun_ref の組み合わせで発生する問題として有名です。Effective STL 50項でも取り上げられており「参照への参照問題」と訳されています。ここでは参照をリファレンスという用語で統一していますので、この問題は「リファレンスへのリファレンス問題」ということになるでしょう。

001 template struct A {
002 void f(const T& t) {} // T がリファレンスだとマズイ!
003 };
004
005 template void f1(void (*pf)(ArgType)) {
006 A a;
007 }
008 void f2(const int&) {}
009
010 void f() {
011 f1(f2); // ArgType が const int& ということは、T も const int& になってしまう。
012 }

標準化委員会はこの問題に対処するため、標準の変更を検討しているそうです。しかし、標準が改訂され、コンパイラベンダがそれに対応するまでにはもう少し時間がかかります。もし、今すぐにでもこの問題を解決したいならば Boost.org を参照しましょう。そこには、まさにこの問題を解決するための boost::call_traits というテンプレートが用意されています。
posted by シンビアン at 08:47| Comment(0) | TrackBack(0) | Symbian OS C++ 実践開発技法 | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
この記事へのトラックバックURL
http://blog.seesaa.jp/tb/12543431

この記事へのトラックバック
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。