constexpr optional() noexcept; // (1) C++17
constexpr optional(nullopt_t) noexcept; // (2) C++17
constexpr optional(const optional& rhs); // (3) C++17
constexpr optional(optional&& rhs) noexcept(see below); // (4) C++17
template <class... Args>
constexpr explicit optional(in_place_t, Args&&... args); // (5) C++17
template <class U, class... Args>
constexpr explicit optional(
in_place_t,
initializer_list<U> il,
Args&&... args); // (6) C++17
template <class U = T>
EXPLICIT constexpr optional(U&& rhs); // (7) C++17
template <class U = T>
explicit(see below) constexpr optional(U&& rhs); // (7) C++20
template <class U>
EXPLICIT optional(const optional<U>& rhs); // (8) C++17
template <class U>
explicit(see below) optional(const optional<U>& rhs); // (8) C++20
template <class U>
explicit(see below) constexpr optional(const optional<U>& rhs); // (8) C++23
template <class U>
EXPLICIT optional(optional<U>&& rhs); // (9) C++17
template <class U>
explicit(see below) optional(optional<U>&& rhs); // (9) C++20
template <class U>
explicit(see below) constexpr optional(optional<U>&& rhs); // (9) C++23
概要
- (1), (2) : 有効値を保持していない状態にする
- (3) : コピーコンストラクタ
- (4) : ムーブコンストラクタ
- (5) : 型
T
のコンストラクタ引数を受け取って、コンストラクタ内で型T
のオブジェクトを有効値として生成し、保持する - (6) : 型
T
のコンストラクタ引数として初期化子リストと任意個の引数を受け取って、コンストラクタ内で型T
のオブジェクトを有効値として生成し、保持する - (7) : 型
T
に変換可能な型U
の値を有効値として受け取り、ムーブして保持する - (8) : 変換可能な
optional
オブジェクトからコピー構築する - (9) : 変換可能な
optional
オブジェクトからムーブ構築する
テンプレートパラメータ制約
- (5) : 型
T
が引数の型Args...
から構築可能であること - (6) : 型
T
が引数の型initializer_list<U>&
とArgs&&...
から構築可能であること - (7) : 型
U
から型T
がムーブ構築可能であること - (8) : 型
U
から型T
がコピー構築可能であること - (9) : 型
U
から型T
がムーブ構築可能であること
効果
- (1), (2) : 有効値を保持していない状態にする。このとき、有効値の型
T
のオブジェクトは構築されない - (3) :
rhs
が有効値を保持していれば、それを*this
にコピーする - (4) :
rhs
が有効値を保持していれば、それを*this
にムーブする。rhs.has_value()
は変更されない - (5) : 可変個の引数
args...
を型T
のコンストラクタ引数として転送して、コンストラクタ内で型T
の有効値を構築して保持する - (6) : 初期化子リスト
il
と可変個の引数args...
を型T
のコンストラクタ引数として転送して、コンストラクタ内で型T
の有効値を構築して保持する - (7) :
rhs
を有効値として、*this
にムーブする - (8) :
rhs
が有効値を保持していれば、それを*this
にコピーする - (9) :
rhs
が有効値を保持していれば、それを*this
にムーブする
例外
- (3) :
- 型
T
のコピーコンストラクタが任意の例外を送出する可能性がある
- 型
- (4) :
- 型
T
のムーブコンストラクタが任意の例外を送出する可能性がある - このオーバーロードの
noexcept
の値は、is_nothrow_move_constructible_v<T>
の値と等価になる
- 型
- (5), (6), (7), (8), (9) :
- 型
T
の選択されたコンストラクタが任意の例外を送出する可能性がある
- 型
delete定義される条件
- (3) : 型
T
がコピー構築可能でないこと - (4) : 型
T
がムーブ構築可能でないこと
定数式に評価される条件
- (3) : 型
T
がトリビアルにコピー構築可能であること - (4) : 型
T
がトリビアルにムーブ構築可能であること - (5) : 型
T
の選択されたコンストラクタがconstexpr
であること - (6) : 型
T
の選択されたコンストラクタがconstexpr
であること - (7) : 型
T
の選択されたコンストラクタがconstexpr
であること
トリビアルに定義される条件
- (3) : 型
T
がトリビアルにコピー構築可能であること - (4) : 型
T
がトリビアルにムーブ構築可能であること
explicitになる条件
- (7) : 型
U
から型T
に暗黙的に型変換ができる場合、このオーバーロードは非explicit
となる。型U
から型T
に明示的な型変換ならできる場合、このオーバーロードはexplicit
となる - (8) : 型
U
から型T
に暗黙的に型変換ができる場合、このオーバーロードは非explicit
となる。型U
から型T
に明示的な型変換ならできる場合、このオーバーロードはexplicit
となる - (9) : 型
U
から型T
に暗黙的に型変換ができる場合、このオーバーロードは非explicit
となる。型U
から型T
に明示的な型変換ならできる場合、このオーバーロードはexplicit
となる
備考
- (5) :
std::in_place_t
はオーバーロードに機能名を付けるためにあり、その型による動的な処理内容への影響はない。このオーバーロードを選択したい場合は、事前定義されている定数std::in_place
を第1引数として指定すること
例
#include <cassert>
#include <optional>
#include <string>
#include <vector>
#include <memory>
struct Base {};
struct Derived : Base {};
int main()
{
// (1)
{
std::optional<int> p;
assert(!p.has_value());
}
// (2)
{
std::optional<int> p = std::nullopt;
assert(!p.has_value());
}
// (3)
{
std::optional<int> a = 3;
std::optional<int> b = a;
assert(a.value() == 3);
assert(b.value() == 3);
}
// (4)
{
std::optional<std::string> a = "Hello";
std::optional<std::string> b = std::move(a);
assert(b.value() == "Hello");
}
// (5)
{
std::optional<std::string> p {std::in_place, 3, 'A'};
assert(p.value() == "AAA");
}
// (6)
{
std::allocator<int> alloc;
std::optional<std::vector<int>> p {std::in_place, {3, 1, 4}, alloc};
assert(p.value()[0] == 3);
assert(p.value()[1] == 1);
assert(p.value()[2] == 4);
}
// (7)
{
// const char*からstd::stringに暗黙的に型変換
std::optional<std::string> p1 = "Hello";
assert(p1.value() == "Hello");
// 整数値からstd::vectorに明示的に型変換
std::optional<std::vector<int>> p2 {3};
assert(p2.value().size() == 3);
}
// (8)
{
std::optional<const char*> a = "Hello";
std::optional<std::string> b = a;
assert(b.value() == "Hello");
}
// (9)
{
std::optional<std::shared_ptr<Derived>> a = std::make_shared<Derived>();
std::optional<std::shared_ptr<Base>> b = std::move(a);
}
}
出力
バージョン
言語
- C++17
処理系
- Clang: 4.0.1 ✅
- GCC: 7.2 ✅
- ICC: ??
- Visual C++: ??
関連項目
参照
- N3406 A proposal to add a utility class to represent optional objects (Revision 2)
- LWG Issue 2756.
optional<T>
shouldforward T
's implicit conversions - LWG Issue 2842.
in_place_t
check foroptional::optional(U&&)
should decayU
- 説明の簡略化のため、このオーバーロードで
in_place_t
への言及は現在していない
- 説明の簡略化のため、このオーバーロードで
- LWG Issue 2900. The copy and move constructors of
optional
are notconstexpr
- P0777R1 Treating Unnecessary
decay
- P0892R2
explicit(bool)
- C++20での
explicit(bool)
構文への対応
- C++20での
- P0602R4
variant
andoptional
should propagate copy/move triviality - P2231R1 Missing
constexpr
instd::optional
andstd::variant