C++14で入りそうで入らなかったoptional
クラスですが、C++1zで入ることになりました。
optional
は、テンプレート引数で指定した型の値を有効値、std::nullopt
という特殊なオブジェクトを無効値と見なす型です。
ひとつの型で有効値と無効値を表すために、int
だったら負の値、ポインタだったらヌル、文字列だったら空文字列を無効値として使用されてきました。これは関数の仕様として無効値の範囲を定義する方法ですが、optional
クラスは型として無効値の表現を持ちます。
#include <iostream> #include <optional> int main() { // 有効値3を代入 std::optional<int> opt = 3; // 有効かを判定 if (opt) { // 有効値を取り出す int& x = opt.value(); std::cout << x << std::endl; } // 無効値を代入 opt = std::nullopt; if (!opt) { std::cout << "nullopt" << std::endl; } }
出力:
3 nullopt
これにより、関数を定義するプログラマが、有効値かエラーかのどちらかを戻り値として返したい場合には、値の仕様を考える必要なく、optional
を戻り値の型に設定すればよくなります。
optional
クラスは、新設される<optional>
ヘッダで定義されます。
Boostと標準の差異
optional
クラスは、Boostで古くから提供されていた機能で、それをベースに標準の仕様が策定されました。標準の仕様が固まっていくにつれてBoostの方も合わせて機能が更新されていっているので、Boost 1.61.0時点では、この2つの差異はかなり小さくなっています。(標準の仕様を考えている人とBoost.Optionalのメンテナは同一人物です)
その前提で、現状の差異は以下のようになっています:
- 標準は全面的に
constexpr
対応している - Boostの無効値は
boost::none
、標準の無効値はstd::nullopt
- 標準では、
any
とvariant
との共通設計のために、有効値を持つか判定するhas_value()
メンバ関数、make_optional()
非メンバ関数が定義される - 標準は
optional<T&>
の部分特殊化が定義されない - 標準では入出力のストリーム演算子が定義されない (出力フォーマットの合意が得られなかった)
- 標準はハッシュサポートがある
補足として、expected
クラスにあるようなモナドインタフェース(bind()
、map()
)や、0 or 1要素のRangeとして扱う機能はありません。
参照
- N1878 A proposal to add an utility class to represent optional objects (Revision 1)
- N3406 A proposal to add a utility class to represent optional objects (Revision 2)
- N3527 A proposal to add a utility class to represent optional objects (Revision 3)
- N3672 A proposal to add a utility class to represent optional objects (Revision 4)
- N3793 A proposal to add a utility class to represent optional objects (Revision 5)
- N3966 Fixes for optional objects
- N3982 Rvalue reference overloads for optional
- N4480 Programming Languages — C++ Extensions for Library Fundamentals
- P0220R0 Adopt Library Fundamentals TS for C++17
- P0220R1 Adopt Library Fundamentals V1 TS Components for C++17 (R1)
- P0032R0 Homogeneous interface for
variant
,any
andoptional
- P0032R1 Homogeneous interface for
variant
,any
andoptional
(Revision 1) - P0032R2 Homogeneous interface for
variant
,any
andoptional
(Revision 2) - P0032R3 Homogeneous interface for
variant
,any
andoptional
(Revision 3) - P0307R0 Making Optional Greater Equal Again
- P0307R2 Making Optional Greater Equal Again
- C++1y
std::optional
のリビジョン3 - Faith and Brave - C++で遊ぼう optional
がC++14入り - Faith and Brave - C++で遊ぼう- C++14の予定から
optional
とdynarray
削除? - Faith and Brave - C++で遊ぼう get
かvalue
か - Faith and Brave - C++で遊ぼう- P0504R0 Revisiting in-place tag types for
any
/optional
/variant
お断り
この記事の内容は、C++1zが正式リリースされる際には変更される可能性があります。正式リリース後には、C++日本語リファレンスサイトcpprefjpの以下の階層の下に解説ページを用意する予定です。