types_is_convertible
types_is_convertible (타입 변환 가능성 판별)
이 페이지는 <type_traits> 헤더에 정의된 std::is_convertible과 std::is_nothrow_convertible 템플릿에 대해 설명해요. 이 템플릿들은 한 타입이 다른 타입으로 암시적으로 변환될 수 있는지, 그리고 그 변환이 예외를 던지지 않는지 컴파일 타임에 판별해 줘요. 주로 SFINAE나 조건부 컴파일에서 타입의 성질을 검사하는 데 사용돼요.
출처: cppreference
본문
정의
<type_traits> 헤더에 정의되어 있어요.
| 템플릿 정의 | (1) | (2) |
|---|---|---|
template < class From , class To > struct is_convertible ; |
(1) | (C++11부터) |
template < class From , class To > struct is_nothrow_convertible ; |
(2) | (C++20부터) |
To가 참조 타입이고 std::declval<From>()을 To에 바인딩할 때 임시 객체가 생성되는 상황이라면, 실제 함수에서는 그러한 바인딩이 잘못된 형식(ill-formed)이더라도 가상 함수의 return 문은 잘 구성된(well-formed) 것으로 간주돼요. (C++26부터)
From 또는 To가 완전한 타입(complete type), (cv 한정된) void, 또는 경계를 알 수 없는 배열이라면 동작이 정의되지 않아요.
위 템플릿 중 하나의 인스턴스화가 직접적으로든 간접적으로든 불완전한 타입에 의존하고, 그 타입이 가상적으로 완성되었을 때 결과가 달라질 수 있다면 동작이 정의되지 않아요.
이 페이지에 설명된 템플릿에 대해 프로그램이 특수화를 추가하면 동작이 정의되지 않아요.
헬퍼 변수 템플릿
| 헬퍼 변수 템플릿 | (C++17부터) | (C++20부터) |
|---|---|---|
template < class From , class To > constexpr bool is_convertible_v = is_convertible < From , To >:: value ; |
(C++17부터) | |
template < class From , class To > constexpr bool is_nothrow_convertible_v = is_nothrow_convertible < From , To >:: value ; |
(C++20부터) |
std::integral_constant에서 상속받은 멤버
멤버 상수
| 멤버 | 설명 |
|---|---|
value [static] |
From이 To로 변환 가능하면 true, 아니면 false (공용 정적 멤버 상수) |
멤버 함수
| 멤버 함수 | 설명 |
|---|---|
operator bool |
객체를 bool로 변환하고 value를 반환해요 (공용 멤버 함수) |
operator() (C++14) |
value를 반환해요 (공용 멤버 함수) |
멤버 타입
| 타입 | 정의 |
|---|---|
value_type |
bool |
type |
std :: integral_constant < bool , value > |
가능한 구현
is_convertible (1) |
|---|
| `namespace detail { template < class T > auto test_returnable ( int ) -> decltype ( void ( static_cast < T ( * )() > ( nullptr )), std :: true_type {} ); template < class > auto test_returnable (...) -> std :: false_type ; template < class From , class To > auto test_implicitly_convertible ( int ) -> decltype ( void ( std :: declval < void ( & )( To ) > ()( std :: declval < From > ())), std :: true_type {} ); template < class , class > auto test_implicitly_convertible (...) -> std :: false_type ; } // namespace detail template < class From , class To > struct is_convertible : std :: integral_constant < bool , ( decltype ( detail :: test_returnable < To > ( 0 )) :: value && decltype ( detail :: test_implicitly_convertible < From , To > ( 0 )) :: value ) |
is_nothrow_convertible (2) |
|---|
template < class From , class To > struct is_nothrow_convertible : std :: conjunction < std :: is_void < From > , std :: is_void < To >> {}; template < class From , class To > requires requires { static_cast < To ( * )() > ( nullptr ); { std :: declval < void ( & )( To ) noexcept > ()( std :: declval < From > ()) } noexcept ; } struct is_nothrow_convertible < From , To > : std :: true_type {}; |
참고
참조 타입, void 타입, 배열 타입, 함수 타입에 대해서도 잘 정의된 결과를 제공해요.
현재 표준은 변환으로 생성된 객체(결과 객체 또는 참조에 바인딩된 임시 객체)의 파괴가 변환의 일부로 간주되는지 여부를 명시하지 않았어요. 이는 LWG issue 3400이에요.
알려진 모든 구현은 P0758R1에서 제안된 대로 파괴를 변환의 일부로 취급해요.
기능 테스트 매크로
| 매크로 | 값 | 표준 | 기능 |
|---|---|---|---|
__cpp_lib_is_nothrow_convertible |
201806L | (C++20) | std::is_nothrow_convertible |
예제
#include <iomanip>
#include <iostream>
#include <string>
#include <string_view>
#include <type_traits>
using namespace std::literals;
class A {};
class B : public A {};
class C {};
class D { public: operator C() { return c; } C c; };
class E { public: template<class T> E(T&&) {} };
static_assert(std::is_convertible_v<B*, A*>);
static_assert(!std::is_convertible_v<A*, B*>);
static_assert(std::is_convertible_v<D, C>);
static_assert(!std::is_convertible_v<B*, C*>);
// Note that the Perfect Forwarding constructor makes the class E be
// “convertible” from everything. So, A is replaceable by B, C, D..:
static_assert(std::is_convertible_v<A, E>);
static_assert(!std::is_convertible_v<std::string_view, std::string>);
static_assert(std::is_convertible_v<std::string, std::string_view>);
int main()
{
auto stringify = []<typename T>(T x)
{
if constexpr (std::is_convertible_v<T, std::string> or
std::is_convertible_v<T, std::string_view>)
return std::quoted(x);
else
return std::to_string(x);
};
const char* three = "three";
std::cout << stringify("one"s) << ' '
<< stringify("two"sv) << ' '
<< stringify(three) << ' '
<< stringify(42) << ' '
<< stringify(42.24) << '\n';
}
가능한 출력:
"one" "two" "three" 42 42.24
같이 보기
| 문서 | 설명 |
|---|---|
is_base_of (C++11) |
한 타입이 다른 타입의 기본 클래스인지 확인해요 (클래스 템플릿) |
is_pointer_interconvertible_base_of (C++20) |
한 타입이 다른 타입의 포인터 상호변환 가능한 (초기) 기본 클래스인지 확인해요 (클래스 템플릿) |
is_pointer_interconvertible_with_class (C++20) |
어떤 타입의 객체가 해당 타입의 지정된 하위 객체와 포인터 상호변환 가능한지 확인해요 (함수 템플릿) |
convertible_to (C++20) |
한 타입이 다른 타입으로 암시적으로 변환 가능함을 명시해요 (개념) |
is_convertible_type is_nothrow_convertible_type (C++26) |
반영된 타입이 다른 타입으로 변환될 수 있는지 확인해요 (함수) |