生ポインタの軽快な代替として使えるクラスを作ってみた。

Boost.Optional Must Go (2) - 野良C++erの雑記帳 の後半に書いた、
「boost::optional はサイズの点でポインタより不利である」
という不満点を解決するためのクラスを作ってみました:


etude::optional_ref
http://gist.github.com/634279


使い方は boost::optionalだいたい同じです。

あるいは、生ポインタと同じ、と言うべきなのかもしれません。

void f1( etude::optional_ref<int> const& );
etude::optional_ref<hoge> f2();

// 普通に参照として
int i = 0;
etude::optional_ref<int> p = i;
*p = 42;

// 引数として
f1( i );
f1( boost::none );

// 関数の戻り値として
if( etude::optional_ref<hoge> p = f2() ) {
  hoge& x = *p;
  // 処理
}

boost::optional と違う点:

  • 生ポインタからの構築が可能(ポインタの代替として使いやすいよう)
  • 等号/不等号による比較が、値の比較ではなくアドレスの比較になっている(同じくポインタの代替として使いやすいよう)
  • etude::make_optional_ref の存在( auto と組み合わせて使うとよし。地味に便利)
  • 当然、中身が違う(各種 type_traits のメタ関数の呼び出し結果も違う*1

生ポインタと違う点:

  • デフォルト構築した時、必ず無効値に初期化される(不定値にならない)
  • アドレスを取る必要がない(利便性のため、アドレスからも作れる)。 & 演算子が多重定義されていても問題なし
  • 単純に delete しようとしてもコンパイルエラーになる(本質は参照なので望ましい動作)
  • [] とか + とかの操作もきちんとコンパイルエラー(同じく参照なので当たり前)
  • 上記をひっくるめて、無効値つきの参照(再設定可能)という意図を示しやすい

総合して、生のポインタ使うより 安全に扱えて、意図も示しやすく、かつ
boost::optional と違い オーバーヘッドも特に無いので、いい感じに使える…筈。

TODO

  • きっちりしたテストコード書く
  • 配列に対して特殊化する

テストコード書きました。
配列に対する特殊化は面倒になったのでやめます。
そこまでいくと生ポインタと大して変わらないですし。

*1:たとえば has_trivial_destructor