생각보다 쉬우면서 까다로우니, 정리를 잘 해보자.
뭐 평범하다. 여기서 출력할 때, 문자열이 print()함수의 << ' ' 로 인해서 한칸씩 띄어져있는게 불편하다.
이 부분을 char부분일때는 특수화시키고 싶다.
우리가 int size 부분은 특수화할 이유가 없고, 오직 typename T만 특수화시켜줘야한다.
그래서 이를 '부분 특수화'라 일컫는다. 여기까진 그래그래 이해가 된다.
방금 위의 print함수는 클래스 밖에 있었다. 그리고 인자를 class 객체를 받아서 활용했다.
근데 생각해보면 print 함수를 그냥 클래스의 멤버함수로 사용해도 문제없다.
물론 멤버로 넣어주면 이렇게 출력형식을 .을 활용해야겠지.
다만 이렇게 되면 특수화가 안되어있어서 다시 문제가 생긴다.
멤버 함수를 부분특수화를 하려면 어떻게 해야할까?
우선 기존의 Static_Array 클래스의 이름을 BASE라는 이름으로 바꾸고
이 BASE 클래스를 상속받는 클래스를 만들었다. 이 때의 template은 부모의 클래스의 template과 동일하다.
그러고 나서, 해당 클래스를 부분 특수화해주었다.
그리고 해당 클래스 안에 기존의 print함수를 오버라이딩해주면, 상속의 특성 때문에 BASE의 다른 함수들을 그대로 가져가면서 오버라이딩을 할 수 있다.
여기까지 읽었으면, 약간 의문이 들 수 있다.
그냥 클래스 전체를 상속없이, 함수 부분만 특수화해주면 안돼? 싶을 수 있다.
나 역시 왜 굳이 이렇게 상속을 이용해서, 클래스를 전체를 상속해서 오버라이딩 해야하는지 의문이 들었는데
이는 '완전 특수화'와 '부분 특수화'를 구분하는 것을 인지해야한다.
template<typename T>
class Storage
{
private:
T m_value;
public:
Storage(T value)
: m_value = value
void print()
{ cout<< m_value << endl;}
};
template<>
void Storage<double>::print()
{ cout<< "This is double!"<<endl; }
이 경우, 멤버함수를 밖에서 특수화할 수 있었던 이유는 템플릿의 모든 매개변수를 전부 특수화 했기 때문이다.
(매개변수가 T 한 개밖에 없는 상황에서 T를 double로 특수화했으므로 모든 매개변수를 특수화한 것임.)
이 경우는 '부분 특수화'가 아닌 '완전 특수화'이다.
클래스 템플릿의 모든 매개 변수를 전부 다 특수화하여 '완전 특수화'한 경우에만 이렇게 멤버함수를
클래스 바깥에서 특수화 하는 것이 가능하다.
결론 : 템플릿 매개변수들이 여러 개일 때 그 중 일부만 부분적으로 특수화 하려고 하는 경우에는
멤버 함수를 클래스 바깥에서 특수화 하기 어렵다! 이유는 함수 오버로딩이 번거로워지는 것.
그럼 해결책은 ?
클래스 자체는 부분 특수화가 가능하므로, 부분 특수화한 클래스 내에서 멤버함수를 특수화하는 것이다.
하지만 클래스를 부분 특수화했을 경우, 내가 부분 특수화한 클래스 내의 멤버함수밖에 없을 것이다.
기존의 것들은 그럼 어떻게? 아까 위의 코드에 있던 상속을 그래서 사용한 것이다!
부모 클래스를 하나 상속받는 자식 클래스를 만들고, 이 자식 클래스를 부분 특수화시키는 것이다.
그러면 아까 올린 이 사진이 이해가 된다.
매개 변수가 두 개(T, size)가 있는데 나는 T만 부분적으로 특수화하고 싶으니,
클래스를 부분특수화 시킨 다음에, 안에 해당 함수를 넣는 것이다.
'C++(따라하며 배우는 C++)' 카테고리의 다른 글
chapter 14 - 1. 예외처리의 기본 (0) | 2021.11.17 |
---|---|
Chapter 13-(4). 템플릿 (포인터, 멤버 함수 한번 더 템플릿) (0) | 2021.11.12 |
Chapter 13-(2). 템플릿 Template (template<> specialization) (0) | 2021.11.09 |
Chapter 13 - (1). 템플릿 Template (0) | 2021.11.07 |
Chapter 12(가상 함수들) 끝. (0) | 2021.11.06 |