std::optional<T>::optional
From cppreference.com
constexpr optional() noexcept; |
(1) | (C++17以降) |
constexpr optional( std::nullopt_t ) noexcept; |
(2) | (C++17以降) |
constexpr optional( const optional& other ); |
(3) | (C++17以降) |
constexpr optional( optional&& other ) noexcept(/* 下記参照 */); |
(4) | (C++17以降) |
template< class U > optional( const optional<U>& other ); |
(5) | (C++17以降) (C++20 以降 constexpr) (条件付き explicit) |
template< class U > optional( optional<U>&& other ); |
(6) | (C++17以降) (C++20 以降 constexpr) (条件付き explicit) |
template< class... Args > constexpr explicit optional( std::in_place_t, Args&&... args ); |
(7) | (C++17以降) |
template< class U, class... Args > constexpr explicit optional( std::in_place_t, |
(8) | (C++17以降) |
template< class U = std::remove_cv_t<T> > constexpr optional( U&& value ); |
(9) | (C++17以降) (条件付き explicit) |
新しいoptionalオブジェクトを構築します。
目次 |
[編集] パラメータ
| その他 | - | 別のoptionalオブジェクト。その格納されている値はコピーされます。 |
| value | - | 含まれる値を初期化するための値 |
| args... | - | 含まれる値を初期化するための引数 |
| ilist | - | 含まれる値を初期化するための初期化子リスト |
[編集] 効果
| オーバーロード | 初期化方法 | 格納されている値の初期化子 | 構築後のhas_value() |
|---|---|---|---|
| (1) | N/A | - | false |
| (2) | |||
| (3) | 直接(リスト以外) | *other | other.has_value()
|
| (4) | std::move(*other) | ||
| (5) | *other | ||
| (6) | std::move(*other) | ||
| (7) | std::forward<Args>(args)... | true | |
| (8) | ilist, std::forward<Args>(args)... | ||
| (9) | std::forward<U>(value) |
[編集] 制約と補足情報
std::is_trivially_copy_constructible_v<T> が true の場合、コンストラクタはトリビアルです。
std::is_trivially_move_constructible_v<T> が true の場合、コンストラクタはトリビアルです。
5) このオーバーロードは、以下のすべての条件が満たされている場合にのみ、オーバーロード解決に参加します。
- std::is_constructible_v<T, const U&> が true。
Tが(cv修飾されている可能性のある)boolでない場合、以下の8つの値はすべて false です[1]- std::is_constructible_v<T, std::optional<U>&>
- std::is_constructible_v<T, const std::optional<U>&>
- std::is_constructible_v<T, std::optional<U>&&>
- std::is_constructible_v<T, const std::optional<U>&&>
- std::is_convertible_v<std::optional<U>&, T>
- std::is_convertible_v<const std::optional<U>&, T>
- std::is_convertible_v<std::optional<U>&&, T>
- std::is_convertible_v<const std::optional<U>&&, T>
このオーバーロードは、explicit(!std::is_convertible_v<const U&, T>) で宣言されているかのように扱われます。
6) このオーバーロードは、以下のすべての条件が満たされている場合にのみ、オーバーロード解決に参加します。
- std::is_constructible_v<T, U>がtrueであること。
Tが(cv修飾されている可能性のある)boolでない場合、以下の8つの値はすべて false です[1]- std::is_constructible_v<T, std::optional<U>&>
- std::is_constructible_v<T, const std::optional<U>&>
- std::is_constructible_v<T, std::optional<U>&&>
- std::is_constructible_v<T, const std::optional<U>&&>
- std::is_convertible_v<std::optional<U>&, T>
- std::is_convertible_v<const std::optional<U>&, T>
- std::is_convertible_v<std::optional<U>&&, T>
- std::is_convertible_v<const std::optional<U>&&, T>
このオーバーロードは、explicit(!std::is_convertible_v<U, T>) で宣言されているかのように扱われます。
Tの初期化に選択されたコンストラクタが constexpr コンストラクタの場合、このコンストラクタも constexpr コンストラクタになります。8) このオーバーロードは、std::is_constructible_v<T, std::initializer_list<U>&, Args...> が true の場合にのみ、オーバーロード解決に参加します。
Tの初期化に選択されたコンストラクタが constexpr コンストラクタの場合、このコンストラクタも constexpr コンストラクタになります。9) このオーバーロードは、以下のすべての条件が満たされている場合にのみ、オーバーロード解決に参加します。
- std::is_constructible_v<T, U>がtrueであること。
- std::decay_t<U>(C++20まで)std::remove_cvref_t<U>(C++20以降) は std::in_place_t でも std::optional<T> でもなく、std::decay_t<U>(until C++20)std::remove_cvref_t<U>(since C++20) です。
Tが(cv修飾されている可能性のある)boolの場合、std::decay_t<U>(until C++20)std::remove_cvref_t<U>(since C++20) はstd::optionalの特殊化ではありません。
このオーバーロードは、explicit(!std::is_convertible_v<U, T>) で宣言されているかのように扱われます。
Tの初期化に選択されたコンストラクタが constexpr コンストラクタの場合、このコンストラクタも constexpr コンストラクタになります。- ↑ 1.0 1.1 言い換えると、
Tは、(cv修飾されている可能性のある)std::optional<U> の型の式(cv修飾されている可能性あり)から構築も変換もできません。
[編集] 例外
3)
Tのコンストラクタによってスローされる例外をスローします。4)
Tのコンストラクタによってスローされる例外をスローします。以下の例外仕様を持ちます。noexcept 指定:
noexcept(std::is_nothrow_move_constructible<T>::value)
5-9)
Tのコンストラクタによってスローされる例外をスローします。[編集] 推論ガイド
[編集] 注意
LWG issue 3836 の解決前は、std::optional<bool> を std::optional<U> から構築する場合、U が bool でない場合、オーバーロード (5,6) がオーバーロード解決に参加しないため、オーバーロード (9) が選択されていました。これは、オーバーロード (5,6) が、T(この場合は bool)が std::optional<U> から構築または変換できる場合に参加しないという制約があったためです。しかし、std::optional::operator bool により、任意の U に対して変換が可能になっていました。
その結果、構築された std::optional<bool> は常に値を含んでいました。その値は、提供された std::optional<U> オブジェクトが値を含むかどうかによって決まり、格納されている値から直接初期化された bool 値ではありませんでした。
std::optional<bool> op_false(false); std::optional<int> op_zero(0); std::optional<int> from_bool(op_false); // OK: contains 0 (initialized from false) std::optional<bool> from_int(op_zero); // DEFECT (LWG 3836): contains true because // op_zero contains a value, even if initializing // bool from that value gives false
| 機能テストマクロ | 値 | 規格 | 機能 |
|---|---|---|---|
__cpp_lib_optional |
202106L |
(C++20) (DR20) |
完全に constexpr ((5,6)) |
[編集] 例
このコードを実行
#include <iostream> #include <optional> #include <string> int main() { std::optional<int> o1, // empty o2 = 1, // init from rvalue o3 = o2; // copy-constructor // calls std::string( initializer_list<CharT> ) constructor std::optional<std::string> o4(std::in_place, {'a', 'b', 'c'}); // calls std::string( size_type count, CharT ch ) constructor std::optional<std::string> o5(std::in_place, 3, 'A'); // Move-constructed from std::string using deduction guide to pick the type std::optional o6(std::string{"deduction"}); std::cout << *o2 << ' ' << *o3 << ' ' << *o4 << ' ' << *o5 << ' ' << *o6 << '\n'; }
出力
1 1 abc AAA deduction
[編集] 欠陥レポート
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| LWG 3836 | C++17 | std::optional<bool> を構築する際std::optional<U> から、オーバーロード解決はU が bool でない場合、オーバーロード (9) を選択する |
常に 変換コピー/ムーブ この場合の |
| LWG 3886 | C++17 | オーバーロード (9) のデフォルトテンプレート引数は T であった |
std::remove_cv_t<T>に変更されました。 |
| P0602R4 | C++17 | コピー/ムーブコンストラクタはトリビアルではない場合がある 基になるコンストラクタがトリビアルであっても |
必要とされる トリビアル性の伝播 |
| P2231R1 | C++20 | 別のstd::optionalからのオーバーロード (5,6) は constexpr ではなかった |
constexprではありませんでした。 |
[編集] 関連項目
| (C++17) |
optional オブジェクトを作成する(function template) |