読者です 読者をやめる 読者になる 読者になる

C++1y - optionalの提案

C++

C++1yでは、boost::optionalをベースとしたクラスが提案されています(元々TR2で導入しようと考えられていた)。提案者は、Boost.Optional作者のFernando Cacciolaさん。


このクラスは、intだったら-1を無効値とし、ポインタだったらNULLを…といったプロジェクトの決め事による無効値ではなく、型で無効値を表現するのに使用します。

optional<int> x = 3; // 有効値を代入
x = nullopt; // 無効値にする

この提案でのboost::optionalとの相違点は、大きなところでは以下になります:

  • 無効値はnullopt。Boostはnone。
  • constexpr対応
  • 入出力ストリームの演算子を提供しない
  • emplaceによる構築。Boostではin_place()関数。

入出力ストリームを提供しないのは、現状その振る舞いについて合意がとれていないからです。
たとえば、optionalを出力する場合、無効値だったらどういう振る舞いになるのか。以下の選択肢が考えられます:

  1. 未定義の振る舞いにする
  2. 何も出力しない
  3. 特殊な文字列を出力する
  4. 有効値の場合に"OPT[3]"、無効値の場合に"OPT[]"というフォーマットで出力する

なんらかの特殊な文字列、もしくはフォーマットで出力するのが良さそうに思えますが、optionalの場合、無効値の出力と同じ文字列が格納される恐れがあります。こういった懸念によって合意が得られていないことから、現状は入出力演算子が定義されないことになっています。


emplaceは、要素型のコンストラクタ引数を受け取って要素を構築する仕組みです。

struct X {
  X(int, string) {}
};

optional<X> x;
x.emplace(3, "hello"); // コンストラクタ引数を渡して有効値を構築

メンバ関数としてのほかに、コンストラクタ用のタグも定義されます。

// emplaceタグを第1引数とするコンストラクタは、
// 要素型のコンストラクタ引数を受け取って有効値を構築する
optional<X> x = {emplace, 3, "hello"};

個人的には、有効値を参照する方法が間接参照演算子しかないのが困るので、議論に参加する機会があったらget()メンバ関数を提案したいところです。
なお、この提案ペーパーにはoptionalの参照実装も含まれています。


N3406 A proposal to add a utility class to represent optional objects (Revision 2)


std::optionalは、以下のGoogle Groupで議論されています。
https://groups.google.com/a/isocpp.org/forum/#!forum/std-proposals


該当するトピック:
std::optional library proposal -- request for feedback
std::optional -- creating optional objects
std::optional -- take 2
投稿は誰でもできるみたいです。