std::is_move_constructible, std::is_trivially_move_constructible, std::is_nothrow_move_constructible
| ヘッダ <type_traits> で定義 |
||
| template< class T > struct is_move_constructible; |
(1) | (C++11以降) |
| template< class T > struct is_trivially_move_constructible; |
(2) | (C++11以降) |
| template< class T > struct is_nothrow_move_constructible; |
(3) | (C++11以降) |
| 型特性 | メンバ定数valueの値 | |
|---|---|---|
Tは参照可能な型 |
Tは参照可能な型ではない | |
| (1) | std::is_constructible<T, T&&>::value | false |
| (2) | std::is_trivially_constructible<T, T&&>::value | |
| (3) | std::is_nothrow_constructible<T, T&&>::value | |
T が不完全型、(cv修飾されている可能性のある)void、または不明な境界を持つ配列の場合、動作は未定義です。
上記のテンプレートのインスタンス化が、直接的または間接的に不完全な型に依存し、その型が仮に完全になった場合にそのインスタンス化が異なる結果を生み出す可能性がある場合、動作は未定義です。
プログラムがこのページで説明されているテンプレートのいずれかに特殊化を追加する場合、動作は未定義です。
目次 |
[編集] ヘルパー変数テンプレート
| template< class T > inline constexpr bool is_move_constructible_v = |
(C++17以降) | |
| template< class T > inline constexpr bool is_trivially_move_constructible_v = |
(C++17以降) | |
| template< class T > inline constexpr bool is_nothrow_move_constructible_v = |
(C++17以降) | |
std::integral_constant から継承
メンバ定数
| value [static] |
Tがムーブ構築可能であればtrue、そうでなければfalse(公開静的メンバ定数) |
メンバ関数
| operator bool |
オブジェクトを bool に変換し、value を返します。 (public member function) |
| operator() (C++14) |
value を返します。 (public member function) |
メンバ型
| 型 | 定義 |
value_type
|
bool |
type
|
std::integral_constant<bool, value> |
[編集] 実装例
template<class T> struct is_move_constructible : std::is_constructible<T, typename std::add_rvalue_reference<T>::type> {}; template<class T> struct is_trivially_move_constructible : std::is_trivially_constructible<T, typename std::add_rvalue_reference<T>::type> {}; template<class T> struct is_nothrow_move_constructible : std::is_nothrow_constructible<T, typename std::add_rvalue_reference<T>::type> {}; |
[編集] 注意
ムーブコンストラクタを持たないが、const T&引数を受け取るコピーコンストラクタを持つ型は、std::is_move_constructibleを満たします。
ムーブコンストラクタは通常noexceptです。なぜなら、そうでなければ強力な例外安全保証を提供するコードでは使用できないからです。
多くの実装では、std::is_nothrow_move_constructibleはデストラクタが例外を投げないかもチェックします。なぜなら、それは実質的にnoexcept(T(arg))であるからです。std::is_trivially_move_constructibleについても同様で、これらの実装ではデストラクタがトリビアルであることも要求されます。GCC bug 51452、LWG issue 2116。
[編集] 例
#include <string> #include <type_traits> struct Ex1 { std::string str; // member has a non-trivial but non-throwing move constructor }; static_assert(std::is_move_constructible_v<Ex1>); static_assert(!std::is_trivially_move_constructible_v<Ex1>); static_assert(std::is_nothrow_move_constructible_v<Ex1>); struct Ex2 { int n; Ex2(Ex2&&) = default; // trivial and non-throwing }; static_assert(std::is_move_constructible_v<Ex2>); static_assert(std::is_trivially_move_constructible_v<Ex2>); static_assert(std::is_nothrow_move_constructible_v<Ex2>); struct NoMove1 { // prevents implicit declaration of default move constructor; // however, the class is still move-constructible because its // copy constructor can bind to an rvalue argument NoMove1(const NoMove1&) {} }; static_assert(std::is_move_constructible_v<NoMove1>); static_assert(!std::is_trivially_move_constructible_v<NoMove1>); static_assert(!std::is_nothrow_move_constructible_v<NoMove1>); struct NoMove2 { // Not move-constructible since the lvalue reference // can't bind to the rvalue argument NoMove2(NoMove2&) {} }; static_assert(!std::is_move_constructible_v<NoMove2>); static_assert(!std::is_trivially_move_constructible_v<NoMove2>); static_assert(!std::is_nothrow_move_constructible_v<NoMove2>); int main() {}
[編集] 欠陥報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| LWG 2196 | C++11 | T&&が形成できない場合の動作が不明確だった | この場合、生成される値はfalseである |
[編集] 関連項目
| (C++11)(C++11)(C++11) |
型が特定の引数に対するコンストラクタを持つかをチェックする (クラステンプレート) |
| 型がデフォルトコンストラクタを持つかをチェックする (クラステンプレート) | |
| (C++11)(C++11)(C++11) |
型がコピーコンストラクタを持つかをチェックする (クラステンプレート) |
| (C++20) |
その型のオブジェクトがムーブ構築可能であることを規定する (コンセプト) |
| (C++11) |
引数をxvalueに変換する (関数テンプレート) |
| (C++11) |
ムーブコンストラクタが例外を投げない場合に引数をxvalueに変換する (関数テンプレート) |