수색…
비고
유형 특성은 컴파일시 서로 다른 유형의 특성을 비교하고 테스트하는 데 사용되는 템플리트 구조입니다. 컴파일 타임에 조건부 논리를 제공하여 특정 방식으로 코드의 기능을 제한하거나 확장 할 수 있습니다. 형질 특성 라이브러리는 다양한 기능을 제공하는 c++11
표준으로 도입되었습니다. 자신 만의 형질 비교 템플릿을 만들 수도 있습니다.
표준 형질
type_traits
헤더는 컴파일 타임에 유형의 특성을 변환하고 점검 할 수있는 템플릿 클래스 및 헬퍼 세트를 포함합니다.
이러한 특성은 일반적으로 템플릿에서 사용자 오류를 확인하고 일반 프로그래밍을 지원하며 최적화를 허용하는 데 사용됩니다.
대부분의 형질 특성은 유형이 몇 가지 기준을 충족하는지 확인하는 데 사용됩니다. 이들은 다음과 같은 형식을 가지고 있습니다 :
template <class T> struct is_foo;
템플리트 클래스가 foo
를 만족하는 유형으로 인스턴스화 된 경우 is_foo<T>
는 std::integral_constant<bool,true>
(일명 std::true_type
)에서 상속받습니다. 그렇지 않으면 std::integral_constant<bool,false>
(일명 std::false_type
). 이것은 특성에 다음 구성원을 제공합니다.
상수
static constexpr bool value
true
경우 T
기준의 충족 foo
, false
, 그렇지 않으면
기능들
operator bool
value
반환 value
bool operator()
value
반환 value
유형
이름 | 정의 |
---|---|
value_type | bool |
type | std::integral_constant<bool,value> |
이 특성은 static_assert
또는 std::enable_if
와 같은 구문에서 사용될 수 있습니다. std::is_pointer
:
template <typename T>
void i_require_a_pointer (T t) {
static_assert(std::is_pointer<T>::value, "T must be a pointer type");
}
//Overload for when T is not a pointer type
template <typename T>
typename std::enable_if<!std::is_pointer<T>::value>::type
does_something_special_with_pointer (T t) {
//Do something boring
}
//Overload for when T is a pointer type
template <typename T>
typename std::enable_if<std::is_pointer<T>::value>::type
does_something_special_with_pointer (T t) {
//Do something special
}
또한 std::add_pointer
및 std::underlying_type
과 같은 형식을 변환하는 다양한 특성이 있습니다. 이러한 특성은 일반적으로 변형 된 형식을 포함하는 단일 type
멤버 형식을 노출합니다. 예를 들어 std::add_pointer<int>::type
은 int*
입니다.
std :: is_same과 타입 관계
std::is_same<T, T>
형식 관계는 두 가지 형식을 비교하는 데 사용됩니다. 부울로 평가되며 유형이 동일하면 true이고 그렇지 않은 경우 false입니다.
예
// Prints true on most x86 and x86_64 compilers.
std::cout << std::is_same<int, int32_t>::value << "\n";
// Prints false on all compilers.
std::cout << std::is_same<float, int>::value << "\n";
// Prints false on all compilers.
std::cout << std::is_same<unsigned int, int>::value << "\n";
std::is_same
형식 관계는 typedef와 관계없이 작동합니다. 이것은 int == int32_t
비교할 때 첫 번째 예제에서 실제로 나타 int == int32_t
그러나 이것은 완전히 명확하지 않습니다.
예
// Prints true on all compilers.
typedef int MyType
std::cout << std::is_same<int, MyType>::value << "\n";
템플리트 화 된 클래스 또는 함수를 부적절하게 사용할 때 경고하기 위해 std::is_same
을 사용합니다.
정적 어설 션과 결합하면 std::is_same
템플릿이 템플릿 클래스 및 함수의 적절한 사용을 시행하는 데 유용한 도구가 될 수 있습니다.
예를 들어 int
에서 입력을 허용하고 두 개의 구조체 중에서 선택할 수있는 함수.
#include <type_traits>
struct foo {
int member;
// Other variables
};
struct bar {
char member;
};
template<typename T>
int AddStructMember(T var1, int var2) {
// If type T != foo || T != bar then show error message.
static_assert(std::is_same<T, foo>::value ||
std::is_same<T, bar>::value,
"This function does not support the specified type.");
return var1.member + var2;
}
기본형 형질
보다 일반적인 유형을 비교하는 여러 유형의 특성이 있습니다.
적분 :
int
, char
, long
, unsigned int
등의 모든 정수 유형에 대해 true로 평가됩니다.
std::cout << std::is_integral<int>::value << "\n"; // Prints true.
std::cout << std::is_integral<char>::value << "\n"; // Prints true.
std::cout << std::is_integral<float>::value << "\n"; // Prints false.
부동 소수점 :
모든 부동 소수점 유형에 대해 true로 평가됩니다. float
, double
, long double
등
std::cout << std::is_floating_point<float>::value << "\n"; // Prints true.
std::cout << std::is_floating_point<double>::value << "\n"; // Prints true.
std::cout << std::is_floating_point<char>::value << "\n"; // Prints false.
열거 형 :
enum class
포함한 모든 열거 형에 대해 true로 평가됩니다.
enum fruit {apple, pair, banana};
enum class vegetable {carrot, spinach, leek};
std::cout << std::is_enum<fruit>::value << "\n"; // Prints true.
std::cout << std::is_enum<vegetable>::value << "\n"; // Prints true.
std::cout << std::is_enum<int>::value << "\n"; // Prints false.
포인터인가?
모든 포인터에 대해 true로 평가합니다.
std::cout << std::is_pointer<int *>::value << "\n"; // Prints true.
typedef int* MyPTR;
std::cout << std::is_pointer<MyPTR>::value << "\n"; // Prints true.
std::cout << std::is_pointer<int>::value << "\n"; // Prints false.
클래스입니다 :
enum class
제외하고 모든 클래스와 구조체에 대해 true로 평가됩니다.
struct FOO {int x, y;};
class BAR {
public:
int x, y;
};
enum class fruit {apple, pair, banana};
std::cout << std::is_class<FOO>::value << "\n"; // Prints true.
std::cout << std::is_class<BAR>::value << "\n"; // Prints true.
std::cout << std::is_class<fruit>::value << "\n"; // Prints false.
std::cout << std::is_class<int>::value << "\n"; // Prints false.
유형 특성
유형 특성은 다른 변수에 배치 할 수있는 수정자를 비교합니다. 이러한 형질 특성의 유용성은 항상 명확하지 않습니다.
참고 : 아래의 예는 최적화되지 않은 컴파일러에서만 개선점을 제공합니다. 복잡한 예가 아니라 단순한 개념 증명입니다.
Fast는 4로 나눕니다.
template<typename T>
inline T FastDivideByFour(cont T &var) {
// Will give an error if the inputted type is not an unsigned integral type.
static_assert(std::is_unsigned<T>::value && std::is_integral<T>::value,
"This function is only designed for unsigned integral types.");
return (var >> 2);
}
상수 :
type이 일정 할 때 true로 평가됩니다.
std::cout << std::is_const<const int>::value << "\n"; // Prints true.
std::cout << std::is_const<int>::value << "\n"; // Prints false.
휘발성인가 :
유형이 일시적 일 때 true로 평가됩니다.
std::cout << std::is_volatile<static volatile int>::value << "\n"; // Prints true.
std::cout << std::is_const<const int>::value << "\n"; // Prints false.
서명 됨 :
이것은 모든 서명 된 유형에 대해 true로 평가됩니다.
std::cout << std::is_signed<int>::value << "\n"; // Prints true.
std::cout << std::is_signed<float>::value << "\n"; // Prints true.
std::cout << std::is_signed<unsigned int>::value << "\n"; // Prints false.
std::cout << std::is_signed<uint8_t>::value << "\n"; // Prints false.
서명되지 않음 :
모든 부호없는 유형에 대해 true로 평가됩니다.
std::cout << std::is_unsigned<unsigned int>::value << "\n"; // Prints true.
std::cout << std::is_signed<uint8_t>::value << "\n"; // Prints true.
std::cout << std::is_unsigned<int>::value << "\n"; // Prints false.
std::cout << std::is_signed<float>::value << "\n"; // Prints false.