最終更新日時: 2026年04月07日 15時36分39秒 (JST)
Akira Takahashi が更新

履歴 編集

class template
<optional>

# std::optional(C++17)

    namespace std {
      template <class T>
      class optional;

      // 参照に対する部分特殊化 (C++26)
      template <class T>
      class optional<T&>;

      // viewコンセプトを有効化する (C++26)
      template<class T>
      constexpr bool ranges::enable_view<optional<T>> = true;

      // std::formatによるフォーマットを無効化する (C++26)
      template<class T>
      constexpr auto format_kind<optional<T>> = range_format::disabled;

      // borrowed_rangeコンセプトを有効化する (C++26)
      template<class T>
      constexpr bool ranges::enable_borrowed_range<optional<T&>> = true;
    }

## 概要

`optional`クラスは、任意の型`T`の値を有効値として、あらゆる型に共通の無効値状態を表現できる型である。

このクラスには、大きく2つの用途がある：

1. オブジェクトの初期化タイミングを遅延させる
2. エラー報告のために、あらゆる型に共通の無効値表現を持たせる

オブジェクトは定義した時点で初期化が行われるが、`optional`クラスはその初期化タイミングを遅延させるために使用できる。この用途には、`std::shared_ptr`のようなスマートポインタを使用することもできるが、このクラスは動的メモリ確保を行わないため、リソース管理ではなく初期化タイミングを遅延させるだけであれば、このクラスの方が適している。

エラー報告について、このクラスを使用しない場合、従来の方法として有効値と無効値は、以下のように表現されていた：

- `int`型の場合、0以上の値を有効な値とし、エラーが起きたら負数を代入する
- ポインタの場合、オブジェクトへのポインタを有効な値とし、どこも指さないヌルポインタを無効値として代入する

このような有効値と無効値の表現は、変数単位もしくはAPI・ライブラリ単位での仕様である。`optional`クラスでは、`nullopt`という特殊な定数を無効値とし、あらゆる型に共通の無効状態を持たせられるようになっている。

このクラスは、ヒープからの動的メモリ確保を行わない。実装は配置newや`std::aligned_storage`のような機能によって、スタック領域のメモリのみを使用する。

## テンプレートパラメータ制約

プライマリテンプレート`optional<T>`の型`T`が以下のいずれかに該当してはならない：

- 参照型
- (CV修飾された)`std::in_place_t`
- (CV修飾された)`std::nullopt_t`

また、型`T`は`std::destructible`要件を満たすこと。

## 参照に対する部分特殊化 (C++26)

このクラスは、`optional<T&>`のように参照を保持できる。内部的には`T`へのポインタとして保持され、代入時には参照先を再束縛 (rebind) する。

`optional<T&>`は以下の特徴をもつ：

- ダングリング参照を防ぐため、一時オブジェクトから構築するオーバーロードは削除定義される
- 代入は参照先の再束縛 (rebind) を行う（参照先オブジェクトへの代入ではない）
- `emplace()`は参照先の再束縛を行う意味論であるため、可変長引数版や`std::initializer_list`版はなく、単一引数のみ受け取る
- `optional<T&>`はトリビアルコピー可能 (trivially copyable) である
- モナド操作 (`and_then()`, `transform()`, `or_else()`) も使用可能

## 備考

このクラスの前身となったBoost Optional Libraryでは、`optional<int&>`のように左辺値参照を要素型とした場合に、無効値の領域を最適化する機能が入っていた。

## メンバ関数

### 構築・破棄

名前 | 説明 | 対応バージョン
--- | --- | ---
`(constructor)` | コンストラクタ | C++17
`(destructor)` | デストラクタ | C++17

### 代入

名前 | 説明 | 対応バージョン
--- | --- | ---
`operator=` | 代入演算子 | C++17
`emplace` | 要素型のコンストラクタ引数から直接構築する | C++17
`swap` | 他の`optional`オブジェクトとデータを入れ替える | C++17
`reset` | 有効値を保持していない状態にする | C++17

### イテレータ

名前 | 説明 | 対応バージョン
--- | --- | ---
`begin` | `optional`をrangeとした時の先頭要素を指すイテレータを取得する | C++26
`end` | `optional`をrangeとした時の末尾要素の次を指すイテレータを取得する | C++26

### 値の観測

名前 | 説明 | 対応バージョン
--- | --- | ---
`operator*` | 間接参照 | C++17
`operator->` | メンバアクセス | C++17
`operator bool` | 有効な値を保持しているかを判定する | C++17
`has_value` | 有効な値を保持しているかを判定する | C++17
`value` | 有効値を取得する | C++17
`value_or` | 有効値もしくは指定された無効値を取得する | C++17

### モナド操作

名前 | 説明 | 対応バージョン
--- | --- | ---
`and_then` | 有効値に対して関数を適用する | C++23
`transform` | 有効値を変換する | C++23
`or_else` | 無効値に対して関数を適用する | C++23

## メンバ型

名前 | 説明 | 対応バージョン
--- | --- | ---
`value_type` | 要素型`T` | C++17
`iterator` | 実装定義のイテレータ型。`contiguous_iterator`、`random_access_iterator`、constexprイテレータのモデルであり、コンテナのイテレータに対するすべての要件を満たす | C++26
`const_iterator` | 実装定義の読み取り専用イテレータ型。`contiguous_iterator`、`random_access_iterator`、constexprイテレータのモデルであり、コンテナのイテレータに対するすべての要件を満たす | C++26

## 非メンバ関数

### ヘルパ関数

名前 | 説明 | 対応バージョン
--- | --- | ---
`make_optional` | 有効な値を保持する`optional`オブジェクトを構築する | C++17

### 値の入れ替え

名前 | 説明 | 対応バージョン
--- | --- | ---
`swap` | 2つの`optional`オブジェクトを入れ替える | C++17

### 比較演算子

名前 | 説明 | 対応バージョン
--- | --- | ---
`operator==` | 等値比較 | C++17
`operator!=` | 非等値比較 | C++17
`operator<=>` | 三方比較 | C++20
`operator<` | 左辺が右辺より小さいかを判定する | C++17
`operator<=` | 左辺が右辺以下かを判定する | C++17
`operator>` | 左辺が右辺より大きいかを判定する | C++17
`operator>=` | 左辺が右辺以上かを判定する | C++17

## 推論補助

名前 | 説明 | 対応バージョン
--- | --- | ---
`(deduction_guide)` | クラステンプレートの推論補助 | C++17

## ハッシュサポート

名前 | 説明 | 対応バージョン
--- | --- | ---
`template <class T> struct hash;` | `hash`クラスの先行宣言 | C++17
`template <class T> struct hash<optional<T>>;` | `hash`クラスの`optional`に対する特殊化 | C++17

## 例

    #include <iostream>
    #include <optional>

    // 除算をする関数。
    // ゼロ割りを試みた場合、無効値が返る
    std::optional<int> safe_divide(int a, int b)
    {
      if (b == 0)
        return std::nullopt;

      return a / b;
    }

    int main()
    {
      // 9/3を計算する
      std::optional<int> result1 = safe_divide(9, 3);
      if (result1) { // 計算に成功した場合、有効値が返る
        int x = result1.value(); // 有効値を取り出す
        std::cout << x << std::endl;
      }

      // 3/0の計算を試みる
      std::optional<int> result2 = safe_divide(3, 0);
      if (!result2) { // 計算に失敗した場合、無効値が返る
        std::cout << "error" << std::endl;
      }
    }

### 出力

    3
    error

### 参照型を保持する例 (C++26)

    #include <print>
    #include <optional>
    #include <map>
    #include <string>

    // コンテナからの要素検索。見つからない場合は無効値を返す
    std::optional<const std::string&>
      find_value(const std::map<int, std::string>& m, int key)
    {
      auto it = m.find(key);
      if (it != m.end()) {
        return it->second;  // 要素への参照を返す (コピーは発生しない)
      }
      return std::nullopt;
    }

    int main()
    {
      std::map<int, std::string> m = {
        {1, "Alice"},
        {2, "Bob"},
        {3, "Charlie"}
      };

      // 値が見つかった場合
      if (auto name = find_value(m, 2)) {
        // コピーではなく参照を保持しているため、効率的にアクセスできる
        std::println("{}", name.value());
      }

      // 値が見つからなかった場合
      if (auto name = find_value(m, 99); !name) {
        std::println("not found");
      }

      // モナド操作との組み合わせ
      auto result = find_value(m, 1)
        .transform([](const std::string& s) { return s.size(); })
        .value_or(0u);
      std::println("{}", result);
    }

#### 出力

    Bob
    not found
    5

## バージョン

### 言語

- C++17

### 処理系

- Clang: 4.0.1 ✅
- GCC: 7.2 ✅
- ICC: ??
- Visual C++: ??

## 参照

- 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` and `optional`
- P0032R1 Homogeneous interface for `variant`, `any` and `optional` (Revision 1)
- P0032R2 Homogeneous interface for `variant`, `any` and `optional` (Revision 2)
- P0032R3 Homogeneous interface for `variant`, `any` and `optional` (Revision 3)
- P0307R0 Making Optional Greater Equal Again
- P0307R2 Making Optional Greater Equal Again
- P0504R0 Revisiting in-place tag types for `any`/`optional`/`variant`
- LWG Issue 3196. `std::optional<T>` is ill-formed is `T` is an array
- P0798R8 Monadic operations for std::optional
- P2988R12 `std::optional<T&>`
  - C++26で参照型`T&`に対する部分特殊化を追加
- P3836R2 `optional<T&>` Should Be Trivially Copyable
  - C++26で`optional<T&>`がトリビアルコピー可能であることを保証