C++ template 과 type 추론
이번 포스팅 정리는 template 과 type 추론 관련해서 정리해 본다. 보통 우리는 최소값 구하는 함수를 아래와 같이 구현할지 모른다.
#include <iostream>
template <typename T>
T GetMin(T a, T b)
{
return a < b ? a : b;
}
int main()
{
int x = 1;
int y = 2;
GetMin(x, y);
GetMin(&x, &y);
return 0;
}
위 코드에서 두번째 호출되는 GetMin 은 애매모호 하다. 어떤 것이 옳다고 볼 수 없기 때문이다. 값을 비교하려는 것인지 주소값을 비교하려는 것인지. 본래 의도라면 해당 변수에 있는 값을 비교해야 했으리라. 그럼 어떻게 접근해야 할까?
T 의 타입이 어떤 타입인지 판단한 후 판단 결과에 맞게 동작하면 되는 것으로 type 추론이 필요한 것이다.
다음 코드를 보자.
#include <iostream>
template <typename T> struct PointType{
enum { value = false };
}
template <typename T> struct PointType<T*>{
enum { value = true };
}
template <typename T>
void IsPointer(T a, T b)
{
if(PointType<T>::value){
wcout << "this is pointer type" << endl;
}
else{
wcout << "this is not pointer type " <<endl;
}
}
int main()
{
int x = 1;
int y = 2;
IsPointer(x, y);
IsPointer(&x, &y);
return 0;
}
위 코드로 포인터 타입인지는 알 수 있으나 들어온 여러 인자에 대해서 판단하고 값을 반환하지는 못 한다. 완벽한 최소값 함수를 구현하고자 한다면 integral_constant 개념도 넣어야 한다. 이것은 나중 포스팅에서 정리하도록 하겠다.
type 추론 관련해서 다른 예를 보도록 해보겠다.
다음 코드를 보도록 하자. 아래 코드의 예는 가상함수를 판별하는 예시이다.
#include <iostream>
using namespace std;
template <typename T>
class vtable{
public:
class child : public T
{
virtual void vfunc(){}
};
enum { value = sizeof(T) == sizeof(child) };
};
template <typename T>
void hasVtable(T& a)
{
if(vtable<T>::value){
cout << "has virtual table." << endl;
}else{
cout << "has not virtual table." << endl;
}
}
class test
{
public:
int a;
virtual void vfunc() {}
};
class test2
{
public:
int a;
void func() {}
};
int main()
{
test a;
test2 b;
hasVtable(a);
hasVtable(b);
return 0;
}
위 코드는 들어온 T 타입의 클래스를 상속받은 후 자식 클래스에 가상함수를 만들어 그 크기를 부모와 비교하는 것이다. 만약 부모가 가상 함수를 가지고 있다면 가상 함수 테이블 크기 때문에 자식과 같을 것이고 그렇지 않다면 자식 클래스 크기가 클 것이다. 이것을 이용한 것이다.
예시 하나만 더 보도록 하자. 다음 예제는 들어온 인자가 배열인지 판별하는 코드이다.
#include <iostream>
using namespace std;
template <typename T>
struct isArray
{
enum { value = false};
enum { size = -1 };
};
template <typename T, int N>
struct isArray<T[N]>
{
enum { value = true};
enum { size = N};
};
template <typename T>
void IsArray(const T& a)
{
if( isArray<T>::value){
wcout << "T is array. size " << isArray<T>::size << endl;
}else{
wcout << "T is not array." << endl;
}
}
int main()
{
int x = 0 ;
int y[5] = {0x00,};
IsArray(x);
IsArray(y);
return 0;
}
보통 template type 추론에서는 template 부분 특수화가 많이 사용되는 것 같다. 메인 템플릿 형태로부터 타입에 맞는 부분 특수화를 받아들여 플래그를 설정하는 그런 방식이 사용된다. std 에서는 이러한 type 추론을 많이 지원하고 있다.
아래는 몇가지 예이다.
std::is_pointer
std::is_member_pointer
std::is_member_object_pointer
std::is_array
std::is_scalar
'프로그래밍 > C/C++' 카테고리의 다른 글
C++ template with member function (0) | 2022.01.13 |
---|---|
C++ Template and Integral_constant (0) | 2022.01.12 |
C++ Perfect forwarding (std::forward 의 역할) (0) | 2022.01.08 |
C++ Universal reference & Reference Collapsing Rules (0) | 2022.01.07 |
C++ rvalue reference 우측값 참조 속성 (0) | 2022.01.07 |