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つの用途がある:
- オブジェクトの初期化タイミングを遅延させる
- エラー報告のために、あらゆる型に共通の無効値表現を持たせる
オブジェクトは定義した時点で初期化が行われるが、optionalクラスはその初期化タイミングを遅延させるために使用できる。この用途には、std::shared_ptrのようなスマートポインタを使用することもできるが、このクラスは動的メモリ確保を行わないため、リソース管理ではなく初期化タイミングを遅延させるだけであれば、このクラスの方が適している。
エラー報告について、このクラスを使用しない場合、従来の方法として有効値と無効値は、以下のように表現されていた:
int型の場合、0以上の値を有効な値とし、エラーが起きたら負数を代入する
- ポインタの場合、オブジェクトへのポインタを有効な値とし、どこも指さないヌルポインタを無効値として代入する
このような有効値と無効値の表現は、変数単位もしくはAPI・ライブラリ単位での仕様である。optionalクラスでは、nulloptという特殊な定数を無効値とし、あらゆる型に共通の無効状態を持たせられるようになっている。
このクラスは、ヒープからの動的メモリ確保を行わない。実装は配置newやstd::aligned_storageのような機能によって、スタック領域のメモリのみを使用する。
テンプレートパラメータ制約
プライマリテンプレートoptional<T>の型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()) も使用可能
- イテレータ (
begin()/end()) およびメンバ型iterator/const_iteratorは、Tが未知境界の配列 (T[]のような型) でないオブジェクト型である場合にのみ提供される。Tが関数型や不完全な配列型のときにイテレータの戻り値型が不正となる問題を避けるためである
備考
このクラスの前身となったBoost Optional Libraryでは、optional<int&>のように左辺値参照を要素型とした場合に、無効値の領域を最適化する機能が入っていた。
メンバ関数
構築・破棄
代入
| 名前 |
説明 |
対応バージョン |
operator= |
代入演算子 |
C++17 |
emplace |
要素型のコンストラクタ引数から直接構築する |
C++17 |
swap |
他のoptionalオブジェクトとデータを入れ替える |
C++17 |
reset |
有効値を保持していない状態にする |
C++17 |
イテレータ
| 名前 |
説明 |
対応バージョン |
begin |
optionalをrangeとした時の先頭要素を指すイテレータを取得する |
C++26 |
end |
optionalをrangeとした時の末尾要素の次を指すイテレータを取得する |
C++26 |
値の観測
モナド操作
メンバ型
非メンバ関数
ヘルパ関数
値の入れ替え
| 名前 |
説明 |
対応バージョン |
swap |
2つのoptionalオブジェクトを入れ替える |
C++17 |
比較演算子
推論補助
ハッシュサポート
| 名前 |
説明 |
対応バージョン |
template <class T> struct hash; |
hashクラスの先行宣言 |
C++17 |
template <class T> struct hash<optional<T>>; |
hashクラスのoptionalに対する特殊化 |
C++17 |
例
出力
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
バージョン
言語
処理系
参照