types_is_move_constructible (이동 생성 가능 여부 판별)
<type_traits> 헤더에 정의된 std::is_move_constructible 계열 타입 특성은 어떤 타입이 이동 생성자(move constructor)로 생성될 수 있는지, 그 생성자가 사소한지(trivial), 예외를 던지지 않는지(nothrow)를 컴파일 타임에 검사해요. 이 템플릿들은 SFINAE나 static_assert와 함께 사용되어 타입의 이동 의미론을 조건부로 활성화하거나 검증하는 데 유용해요.
출처: cppreference
본문
정의
<type_traits> 헤더에 정의되어 있어요.
<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부터) |
만약 T가 완전한 타입(complete type)이 아니거나, (cv 한정을 포함한) void이거나, 경계를 알 수 없는 배열(array of unknown bound)이라면 동작은 정의되지 않아요. 또한 위 템플릿 중 하나의 인스턴스화가 불완전한 타입에 직간접적으로 의존하는데, 그 타입이 가상으로 완성되었을 때 결과가 달라질 수 있다면 동작은 정의되지 않아요. 이 페이지에 설명된 템플릿들에 대해 프로그램이 특수화를 추가하면 동작은 정의되지 않아요.
헬퍼 변수 템플릿
| 템플릿 |
버전 |
template < class T > constexpr bool is_move_constructible_v = is_move_constructible < T >:: value ; |
(C++17부터) |
template < class T > constexpr bool is_trivially_move_constructible_v = is_trivially_move_constructible < T >:: value ; |
(C++17부터) |
template < class T > constexpr bool is_nothrow_move_constructible_v = is_nothrow_move_constructible < T >:: value ; |
(C++17부터) |
std::integral_constant에서 상속됨
멤버 상수
| 이름 |
설명 |
value [static] |
T가 이동 생성 가능하면 true, 아니면 false (공용 정적 멤버 상수) |
멤버 함수
| 이름 |
설명 |
operator bool |
객체를 bool로 변환하며 value를 반환해요 (공용 멤버 함수) |
operator() (C++14) |
value를 반환해요 (공용 멤버 함수) |
멤버 타입
| 타입 |
정의 |
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로 선언되는데, 그렇지 않으면 강한 예외 보장(strong exception guarantee)을 제공하는 코드에서 사용할 수 없기 때문이에요. 많은 구현에서 std::is_nothrow_move_constructible은 사실상 noexcept(T(arg))이므로 소멸자가 예외를 던지는지도 확인해요. std::is_trivially_move_constructible도 마찬가지로, 이러한 구현에서는 소멸자가 사소한지도 요구해요 (GCC 버그 51452, LWG 이슈 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임 |
같이 보기
| 템플릿/개념 |
설명 |
is_constructible, is_trivially_constructible, is_nothrow_constructible (C++11) |
특정 인수에 대한 생성자가 있는지 검사해요 (클래스 템플릿) |
is_default_constructible, is_trivially_default_constructible, is_nothrow_default_constructible (C++11) |
기본 생성자가 있는지 검사해요 (클래스 템플릿) |
is_copy_constructible, is_trivially_copy_constructible, is_nothrow_copy_constructible (C++11) |
복사 생성자가 있는지 검사해요 (클래스 템플릿) |
move_constructible (C++20) |
어떤 타입의 객체가 이동 생성될 수 있음을 명시하는 개념 |
move (C++11) |
인수를 xvalue로 변환해요 (함수 템플릿) |
move_if_noexcept (C++11) |
이동 생성자가 예외를 던지지 않으면 인수를 xvalue로 변환해요 (함수 템플릿) |
is_move_constructible_type, is_trivially_move_constructible_type, is_nothrow_move_constructible_type (C++26) |
반영된 타입이 rvalue 참조로부터 생성될 수 있는지 검사해요 (함수) |
더 알아보기 (Learn more)
cppreference