본문 바로가기

Program Languege/C/C++

템플릿 - 3

템플릿 - 3 템플릿의 특수화

 

 

 

특수화라는 의미보다는 예외의 경우에 대한 처리라는 의미로 이해하면 좀 더 이해하기 쉬울 것이라 생각된다.

 

예시를 하나 들고 설명을 하도록 하겠다.

 

Ex>

 

template <typename T>

T Max(T a, T b)

{

      return a > b ? a : b;

}

 

int main(void)

{

    cout << Max(11, 15) << endl;

    cout << Max('a', 'b') << endl;

    cout << Max("Simple", "Template") << endl;

 

    return 0;

}

 

위의 경우 결과가 어떻게 되겠는가? 첫번째와 두번째의 경우 의도한 대로 맞게 연산 결과가 나올 것이다. 하지만 마지막의 경우 어떤 연산결과가 나올까? 문자열의 길이? 문자열 내의 문자의 크기 비교? 이 경우엔 단순히 주소 값의 크기 비교 결과가 반환된다.

 

그렇다면 이런 경우 어떻게 해야할까?

 

이렇게 함수 템플릿의 특수한 경우의 예외처리를 함수 템플릿의 특수화라고 한다. 함수 템플릿의 특수화를 보자.

 

문자열의 길이 비교를 의도한 것에 대한 처리라면 다음과 같이 구현하면 된다.

 

template <>

char* Max(char *a, char *b)

// char* Max<char *>(char *a, char *b) 이처럼 <char *>로 자료형을 명시해주어도 된다.

{

     return strlen(a) > strlen(b) ? a : b;

}

 

문자열 내의 문자 크기 비교의 경우는

 

template <>

const char* Max(const char *a, const char *b)

// const char* Max<const char *>(char *a, char *b) 여기도 <const char *>로 자료형을 명시해주어도 된다.

{

      return strcmp(a, b) > 0 ? a : b;

}

 

첫번째는 char*형에 대해서 특수화한 것이며 두번째는 const char*에 대해 특수화 한 것이다. T의 자리에 자료형을 명시해놓고 그에따라 달라지는 내부를 정의해주면 되겠다. 그럼 전달 인자에 따라 함수를 구별해 호출하게 된다.

 

 

 

 

클래스 템플릿의 특수화도 마찬가지로 클래스 템플릿의 특수한 경우에 대한 예외처리를 말한다.

Ex>

 

template <typename T>

class Test

{

private:

     T m_Data;

 

public:

     Test(T data) : m_Data(data) {  }

     void ShowData()

     {

            cout << m_Data << endl;

     }

};

 

int main(void)

{

     Test<int> test1(100);

     test1.ShowData();

 

     char* str = new char[10];

     strcpy_s(str, 10, "abcdef");

 

     Test<char *> test2(str);

      

     delete [] str;       

 

     test2.ShowData();

  

      return 0;

}

 

 

위와 같은 경우 test2가 생성은 잘 될테지만 str이 해제되고 나면 문제가 발생할 수 있다.

이런 경우를 막기 위해 클래스 템플릿 특수화를 하면

 

template <>

class Test <char *>

{

private:

    char *m_Data;

 

public:

    Test(char * data)

    {

           m_Data = new char[strlen(data) + 1];

           strcpy(m_Data, data);

    }

    ~Test()

    {

           delete [] m_Data;

    }

    void ShowData()

    {

           cout << m_Data << endl;

    }

};

 

이와 같이 생성자와 소멸자를 추가로 정의하여 예외 처리를 해주면 되겠다.

 

 

이외에도 클래스 템플릿의 부분 특수화가 있다. 부분 특수화는 결정되지 않은 자료형이 두개 이상인 경우 그중 하나에 대해 결정하고 처리하는 것을 말한다.

 

template< typename T1, typename T2>

class Test

{

private:

     T1 m_Data1;

     T2 m_Data2;

 

public:

     Test(T1 data1, T2 data2) : m_Data1(data1), m_Data2(data2) { }

     void ShowData()

     {

            cout << "Data1 : " << m_Data1 << " ,  Data2 : " << m_Data2 << endl;

     }

};

 

위와 같은 경우

 

template<typename T1>

class Test<T1, double>

{

private:

     T1 m_Data1;

     double m_Data2;

 

public:

     Test(T1 data, double data2) : m_Data(data1), m_Data(data2) { }

     void ShowData()

     {

             cout << "Data1 : " << m_Data1 << ", (double)Data2 : " << m_Data2 << endl;

     }

}

 

이런 식의 부분 특수화가 가능하다.

 

 

 

 

- 출처 : 윤성우 열혈 C++ 프로그래밍

 

 

'Program Languege > C/C++' 카테고리의 다른 글

const의 선언 위치  (0) 2014.02.20
템플릿 - 4  (0) 2013.03.19
템플릿 - 2  (0) 2013.03.19
템플릿 - 1  (0) 2013.03.19
순수 가상함수  (0) 2013.03.19