std::is_move_assignable, std::is_trivially_move_assignable, std::is_nothrow_move_assignable
Min standard notice:
Header: <type_traits>
If T is not a complete type, (possibly cv-qualified) void, or an array of unknown bound, the behavior is undefined.
# Declarations
template< class T >
struct is_move_assignable;
(since C++11)
template< class T >
struct is_trivially_move_assignable;
(since C++11)
template< class T >
struct is_nothrow_move_assignable;
(since C++11)
# Notes
The trait std::is_move_assignable is less strict than MoveAssignable because it does not check the type of the result of the assignment (which, for a MoveAssignable type, must be T&), nor the semantic requirement that the target’s value after the assignment is equivalent to the source’s value before the assignment.
The type does not have to implement a move assignment operator in order to satisfy this trait; see MoveAssignable for details.
# Example
#include <iostream>
#include <string>
#include <type_traits>
struct Foo { int n; };
struct NoMove
{
// prevents implicit declaration of default move assignment operator
// however, the class is still move-assignable because its
// copy assignment operator can bind to an rvalue argument
NoMove& operator=(const NoMove&) { return *this; }
};
int main()
{
std::cout << std::boolalpha
<< "std::string is nothrow move-assignable? "
<< std::is_nothrow_move_assignable<std::string>::value << '\n'
<< "int[2] is move-assignable? "
<< std::is_move_assignable<int[2]>::value << '\n'
<< "Foo is trivially move-assignable? "
<< std::is_trivially_move_assignable<Foo>::value << '\n'
<< "NoMove is move-assignable? "
<< std::is_move_assignable<NoMove>::value << '\n'
<< "NoMove is nothrow move-assignable? "
<< std::is_nothrow_move_assignable<NoMove>::value << '\n';
}
# Defect reports
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| LWG 2196 | C++11 | the behavior was unclear if T&& cannot be formed | the value produced is false in this case |