C++ Chapter 13.6 : 함수 부분 특수화

Date:     Updated:

카테고리:

태그:

인프런에 있는 홍정모 교수님의 홍정모의 따라 하며 배우는 C++ 강의를 듣고 정리한 필기입니다. 😀
🌜 [홍정모의 따라 하며 배우는 C++]강의 들으러 가기!


chapter 13. 템플릿 : 클래스 템플릿 특수화

특수화 : 템플릿에서 특정 타입에 대해서 다른 실행 처리를 하고 싶을 때 그 타입에 대해서만 특수화.

🌼 부분 특수화란?

  • 완전 특수화 👉 템플릿 매개 변수들을 전부 다 특수화 함
  • 부분 특수화 👉 템플릿 매개 변수들이 여러개일 때 그 중 일부만 특수화 함
    • 전역 함수의 경우 문제 없이 가능
    • 멤버 함수의 경우 클래스 외부에선 부분 특수화 불가능
      • 클래스 내부에서만 가능하므로 상속을 이용함


🔔 ‘일반 전역 함수’를 부분 특수화

특수화 하기 전

#include <iostream>
using namespace std;

template<typename T, int size>
class StaticArray
{
private:
    T m_array[size];
public:
    
    T * getArray() { return m_array; }
    
    T& operator [] (int index)
    {
        return m_array[index];
    }
};


template<typename T, int size>
void print(StaticArray<T, size> & array)
{
    for (int count = 0; count < size; ++count)
        cout << array[count] << ' ';  // 🤟🤟
    cout << endl;
}


int main()
{
    StaticArray<int, 4> int4;
	int4[0] = 1;
	int4[1] = 2;
	int4[2] = 3;
	int4[3] = 4;
    print(int4);
    
    StaticArray<char, 14> char14;
    strcpy_s(char14.getArray(), 14, "Hello, World");
    print(char14);
    
    return 0;
}
💎출력💎

1 2 3 4
H e l l o ,   W o r l d   ?
  • 클래스 템플릿 StaticArray 는 매개 변수 int size 를 가진다.
  • print 함수는 멤버 함수가 아닌 전역 일반 함수다.
    • 템플릿으로 구체화되는 클래스인 StaticArray 타입의 참조 & 매개변수를 받을 뿐
  • // 🤟🤟 이 부분을 고쳐서 char 타입으로 특수화 되었을땐 공백 한칸씩 띄지 않도록 해보자.


특수화 하기

template<int size>
void print(StaticArray<char, size> & array)
{
    for (int count = 0; count < size; ++count)
        cout << array[count];  // 🤟요기가 다름🤟
    cout << endl;
}
💎출력💎

1 2 3 4
Hello, World
  • 특수화 해도 매개변수는 똑같이 가져가므로 template<int size> 상단에 붙여주기.
    • Tchar로 변경
  • char 타입에만 특수화를 해서 이제 띄어쓰기 되지 않는 것을 볼 수 있다.


🔔 매개 변수가 있는 ‘멤버 함수’를 특수화

미리 내가 쓴 답변 첨부..☆

image

image

image

image

문제점

  • 멤버 함수를 특수화 하기는 까다롭다.

    • print() 가 일반 전역 함수일 땐 print(StaticArray<char, size> & array) 라는 매개 변수가 1개있는 함수였지만
    • print() 가 StaticArray의 멤버 함수가 될 땐 그냥 매개 변수 없는 *print()* 로 표현한다.
      • 이미 StaticArray의 멤버 함수이기 때문에 StaticArray 타입의 객체를 참조로 받을 필요 없이 그냥 *this를 사용하면 된다.
        template<typename T, int size>
        class StaticArray
        {
        private:
            T m_array[size];
        public:
        
            T * getArray() { return m_array; }
        
            T& operator [] (int index)
            {
                return m_array[index];
            }
        
            void print()
            {
                for (int count = 0; count < size; ++count)
                    cout << (*this)[count] << ' ';  // ⭐ array 대신 (*this)
                cout << endl;
            }
        };
        
  • 문제점 👉 특수화는 클래스 밖에서 이루어지는데 더군다나 매개 변수도 없으니 *(this) 를 어떻게 표현할지 까다로워진다.

    • *(this) 자리에 StaticArray 타입의 객체가 있어야 하는데 매개 변수를 통해 받는 것도 없고 클래스 바깥에서 특수화 하니 *(this)를 사용할 수도 없는 문제가 발생
    • 해결 👉 상속 + 오버라이딩으로 해결!

해결책

자식 클래스를 특수화를 하면서 그 안에서 오버라이딩 하면 *this 사용이 가능해진다.

#include <iostream>
#include <stdio.h>

using namespace std;

template<typename T, int size>
class StaticArray_BASE
{
private:
	T m_array[size];
public:

	T * getArray() { return m_array; }

	T& operator [] (int index)
	{
		return m_array[index];
	}

	void print()
	{
		for (int count = 0; count < size; ++count)
			cout << (*this)[count] << ' ';
		cout << endl;
	}
};


template<typename T, int size>
class StaticArray : public StaticArray_BASE<T, size>
{
};


template<int size>
class StaticArray<char, size> : public StaticArray_BASE<char, size>
{
public:
	void print()
	{
		for (int count = 0; count < size; ++count)
			cout << (*this)[count];
		cout << endl;
	}
};


int main()
{
	StaticArray<int, 4> int4;
	int4[0] = 1;
	int4[1] = 2;
	int4[2] = 3;
	int4[3] = 4;
	int4.print();

	StaticArray<char, 14> char14;
	strcpy_s(char14.getArray(), 14, "Hello, World");
	char14.print();

	return 0;
}


  1. 기존 StaticArray 클래스 이름을 StaticArray_Base 로 바꿔주자. 기존 클래스를 부모 클래스로 할 것.
       template<typename T, int size>
       class StaticArray_BASE
       {
       private:
           T m_array[size];
       public:
    
           T * getArray() { return m_array; }
    
           T& operator [] (int index)
           {
               return m_array[index];
           }
    
           void print()
           {
               for (int count = 0; count < size; ++count)
                   cout << (*this)[count] << ' ';  // ⭐ array 대신 (*this)
               cout << endl;
           }
       };
    
  2. StaticArray_Base를 상속하는 StaticArray 자식 클래스를 만든다. 빈 클래스로 만들어 온전히 자기 것 없이 전부 다 상속 받도록 한다.
      template <typename T, int size>
      class StaticArray : public StaticArray_Base<T, size>
      {
      };
    
  3. 빈 자식 클래스인 StaticArray 자식클래스를 특수화 하고 그 안에서 오버라이딩 해준다.이제 *this 사용이 가능해진다. 상속으로 StaticArray_BASE의 정보를 받았기 때문에.
      template<int size>
      class StaticArray<char, size> : public StaticArray_BASE<char, size>
      {  
      public:
       void print()
       {
           for (int count = 0; count < size; ++count)
               cout << (*this)[count];
           cout << endl;
       }
      };
    


🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

Cpp 카테고리 내 다른 글 보러가기

댓글 남기기