パート LI. std::optional ( C++17 )

目次

332. has_value メンバー関数
333. std::optional を使った関数オブジェクトのバインド

std::optional は C++17 から導入されたコンテナです。

コンテナ内にデータがあるか無いか分からないときに使うことを念頭としています。

std::optional<T> は T 型『または』空のクラス・型を保持します。

この空のクラス・型は std::nullopt_t という型として定義できます。

具体的には以下2つのいずれかとなります。

関数の戻り値が std::nullopt_t 型のオブジェクトになるようにしておけば、関数が失敗するような場合でもフェイルセーフに処理ができます。

例えば関数が通常返すデータが文字列だとして、データが未初期であれば { } や std::nullopt として戻すという前提で考えると、コール側ではそのための処理を設計する必要がないのは大きな利点です。

value 関数
std::optional の値を取得する。値が空の場合は例外( std::bad_optional_access )を投げる
value_or 関数
std::optional の値を取得する。値が空の場合のデフォルト値も設定する。

value_or 関数の宣言については以下のようになります。

template< class U >
constexpr T value_or( U&& default_value ) const&;

default_value に適当な値を設定できます。

default_value に設定した値は std::optional オブジェクトの値が空の場合に使われます。

では簡単な例を考えてみましょうかね。

main.cpp. 

  1 #if __cplusplus != 201703L
  2 # pragma message "-std=c++17を指定してください"
  3 #endif
  4
  5 #include <optional>
  6 #include <iostream>
  7
  8 std::optional<std::string_view> ret_string()
  9 {
 10   return std::string_view("Hello");
 11 }
 12
 13 std::optional<std::string_view> ret_null()
 14 {
 15   return std::nullopt;
 16 }
 17
 18 int main()
 19 {
 20   std::cout << ret_string().value_or("no return") << '\n';
 21   std::cout << ret_null().value_or("no return") << '\n';
 22   std::cout << ret_string().value() << " World!"<< '\n';
 23   return 0;
 24 }

これをビルドすると以下のようになります。

$ g++ main.cpp -std=c++17
$ ./a.out
Hello
no return
Hello World!

ret_string 関数は string_view を戻し、 ret_null 関数は空の型データを返します。

  8 std::optional<std::string_view> ret_string()
  9 {
 10   return std::string_view("Hello");
 11 }
 12
 13 std::optional<std::string_view> ret_null()
 14 {
 15   return std::nullopt;
 16 }

もちろんこんな風に関数を2つに分ける事は実際の開発では行いませんが、何かあったら std::nullopt や { } を返せば良いというのは便利です。

Copyright 2017-2018, by Masaki Komatsu