namespace std {
template <class T>
class optional;
}
概要
optional
クラスは、任意の型T
の値を有効値として、あらゆる型に共通の無効値状態を表現できる型である。
このクラスには、大きく2つの用途がある:
- オブジェクトの初期化タイミングを遅延させる
- エラー報告のために、あらゆる型に共通の無効値表現を持たせる
オブジェクトは定義した時点で初期化が行われるが、optional
クラスはその初期化タイミングを遅延させるために使用できる。この用途には、std::shared_ptr
のようなスマートポインタを使用することもできるが、このクラスは動的メモリ確保を行わないため、リソース管理ではなく初期化タイミングを遅延させるだけであれば、このクラスの方が適している。
エラー報告について、このクラスを使用しない場合、従来の方法として有効値と無効値は、以下のように表現されていた:
int
型の場合、0以上の値を有効な値とし、エラーが起きたら負数を代入する- ポインタの場合、オブジェクトへのポインタを有効な値とし、どこも指さないヌルポインタを無効値として代入する
このような有効値と無効値の表現は、変数単位もしくはAPI・ライブラリ単位での仕様である。optional
クラスでは、nullopt
という特殊な定数を無効値とし、あらゆる型に共通の無効状態を持たせられるようになっている。
このクラスは、ヒープからの動的メモリ確保を行わない。実装は配置newやstd::aligned_storage
のような機能によって、スタック領域のメモリのみを使用する。
テンプレートパラメータ制約
型T
が以下のいずれかに該当してはならない:
- 参照型
- (CV修飾された)
std::in_place_t
- (CV修飾された)
std::nullopt_t
また、型T
はstd::destructible
要件を満たすこと。
備考
このクラスの前身となったBoost Optional Libraryでは、optional<int&>
のように左辺値参照を要素型とした場合に、無効値の領域を最適化する機能が入っていた。
標準ライブラリのoptional
クラスには現在、参照を持たせることはできない。
メンバ関数
構築・破棄
名前 | 説明 | 対応バージョン |
---|---|---|
(constructor) |
コンストラクタ | C++17 |
(destructor) |
デストラクタ | C++17 |
代入
名前 | 説明 | 対応バージョン |
---|---|---|
operator= |
代入演算子 | C++17 |
emplace |
要素型のコンストラクタ引数から直接構築する | C++17 |
swap |
他のoptional オブジェクトとデータを入れ替える |
C++17 |
reset |
有効値を保持していない状態にする | C++17 |
値の観測
名前 | 説明 | 対応バージョン |
---|---|---|
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 |
非メンバ関数
ヘルパ関数
名前 | 説明 | 対応バージョン |
---|---|---|
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;
}
}
#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) { // 計算に成功した場合、有効値が返る
出力
3
error
バージョン
言語
- 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
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
- P0504R0 Revisiting in-place tag types for
any
/optional
/variant
- LWG Issue 3196.
std::optional<T>
is ill-formed isT
is an array - P0798R8 Monadic operations for std::optional