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_tcheck foroptional::optional(U&&)should decayU- 説明の簡略化のため、このオーバーロードで
in_place_tへの言及は現在していない
- 説明の簡略化のため、このオーバーロードで
- LWG Issue 2900. The copy and move constructors of
optionalare notconstexpr - P0777R1 Treating Unnecessary
decay - P0892R2
explicit(bool)- C++20での
explicit(bool)構文への対応
- C++20での
- P0602R4
variantandoptionalshould propagate copy/move triviality - P2231R1 Missing
constexprinstd::optionalandstd::variant