아래와 같은 코드를 생각해보자.
template<typename T>
inline T Max(T a, T b) { return a < b ? b : a; }
int main(int argc, char* argv[])
{
int x = 10, y = 20;
Max(x, y);
Max(&x, &y);
}
Max 함수는 함수 템플릿이므로 위의 호출들은 아무 문제없이 수행될 것이다. 하지만 두번째 호출은 인자로 정수값의 주소를 넘기므로 T는 int* 로 추론될 것이며, 이 함수는 두 주소값을 비교한다. 이는 의미없는 행위이며, 실제로 사용자가 원하는 것은 아래와 같이 인자가 포인터일 경우에는 역참조한 값에 대한 비교일 것이다.
template<typename T>
inline T Max(T a, T b)
{
if (T is pointer-type)
return *a < *b ? b : a;
return a < b ? b : a;
}
위의 함수에서 T가 pointer 타입인지를 판별하기 위해서 필요한 것이 TypeTraits이다.
TypeTraits는 컴파일 시간에 타입에 대한 다양한 속성을 얻어내는 기술이다. 예를 들어 T가 포인터인지를 판별하는 TypeTrait는 다음과 같이 정의된다.
// primary template
template<typename T> struct IsPointer
{
enum { kValue = false };
};
// partial specialization
template<typename T> struct IsPointer<T*>
{
enum { kValue = true };
};
template<typename T> void foo(const T& a)
{
if (IsPointer<T>::kValue)
cout << "T: pointer" << endl;
else
cout << "T: not pointer" << endl;
}
int main(int argc, char* argv[])
{
int n = 0;
foo(n); //< T: not pointer
foo(&n); //< T: pointer
return 0;
}
이제 컴파일 시간에 임의의 타입이 포인터 타입인지 아닌지를 판별할 수 있는 도구를 얻었다. 하지만 이것만으로는 위의 Max 함수가 완성되지 않는다. (실제로 컴파일 에러가 발생한다.) 이에 대해서는 다음에 다시 언급할 것이다.
Pointer 타입을 판별하는 것 외에 TypeTraits 테크닉은 다양한 것들을 할 수 있는데, 이번에는 배열을 판별하는 Trait를 만들어보자.
// primary template
template<typename T> struct IsArray
{
enum { kValue = false };
enum { kSize = -1 };
};
// primary template의 인자가 한개라도 부분전문화 버전은 여러개가 가능하다.
template<typename T, int N> struct IsArray<T[N]>
{
enum { kValue = true };
enum { kSize = N };
};
template<typename T> void bar(const T& a)
{
if (IsArray<t>::kValue)
cout << "배열입니다. 크기는 " << IsArray<t>::kSize << endl;
else
cout << "배열이 아닙니다." << endl;
}
int main(int argc, char* argv[])
{
int a = 0;
int b[10] = {0};
bar(a); //< 배열이 아닙니다.
bar(b); //< 배열입니다. 크기는 10
return 0;
}
도전과제: has_virtual_function<T>
- 타입 T가 가상함수를 포함하고 있으면 kValue = true, 아니면 kValue = false
- Hint: 어떤 타입 T가 가상함수를 포함하고 있으면, T에는 가상함수 테이블을 가리키는 포인터가 추가된다.
'NC University > Advanced C++' 카테고리의 다른 글
1일차 - Template 부분 전문화 (0) | 2021.06.14 |
---|---|
6일차 - 단위전략 기반의 클래스 디자인 (0) | 2015.11.24 |
6일차 - thin template (0) | 2015.11.04 |
6일차 - CRTP (Curiosly Recurring Template Pattern) (0) | 2015.10.30 |
6일차 - checked delete (0) | 2015.10.21 |