템플릿과 일반화 프로그래밍 📏
안녕하세요! 두두코딩 입니다 ✋
오늘은 Effective C++ 항목 41에 대해 알아보겠습니다.
🖇 소스코드에 마우스를 올리고 copy 버튼을 누를 경우 더 쉽게 복사할 수 있습니다!
궁금한 점, 보안점 남겨주시면 성실히 답변하겠습니다. 😁
+ 감상평 댓글로 남겨주시면 힘이됩니다. 🙇
명시적 인터페이스와 암시적 인터페이스
명시적 인터페이스
객체 지향 프로그래밍의 세계를 움직이는 축을 나누자면, 명시적 인터페이스와 런타임 다형성이다.
class Widget {
public:
Widget() {};
virtual ~Widget();
virtual std::size_t size() const;
virtual void normalize();
void swap(Widget& other);
...
};
void doProcessing(Widget& w)
{
if (w.size() > 10 && w !=someNastyWidget) {
Widget temp(w);
temp.normalize();
temp.swap(w);
}
}
위 코드는 우리가 객체지향에서 일반적으로 사용하는 코드이다.
-
w
같은 경우Widget
타입으로 선언되어져 있기 때문에Widget
과 관련된 인터페이스를 지원해야한다. 해당 인터페이스 같은 경우 “소스코드” 를 통해 찾으면 어떤 형태인지 알 수 있다. 이와 같이 “소스코드” 를 통해 알 수 있는 인터페이스를 우리는 명시적 인터페이스라고 부른다. -
또한,
Widget
내부에virtual
로 구성된 함수들 즉, 가상함수들 같은 경우 런타임 시점에 virtual table를 확인해 맵핑되는 구조로 이루어진다. 이와 같은 호출을 런타임 다형성에 의해 이루어진다고 말한다.
암시적 인터페이스
템플릿 일반화 프로그래밍의 세계에서는 명시적 인터페이스와 런타임 다형성이 존재하긴 하지만, 더 중요한 개념이 등장한다. 바로 암시적 인터페이스 와 컴파일 다형성 이다.
template<typename T>
void doProcessing(T& w)
{
if (w.size() > 10 && w != someNastyWidget) {
T temp(w);
temp.normalize();
temp.swap(w);
}
}
위와 같이 소스코드가 작성되어질 경우 w
에 대해서 어떻게 말할 수 있을까?
-
w
는 T 타입으로 지원해야되는 인터페이스는size
normalize
swap
과 같은 멤버함수들이다. 뿐만아니라 부등연산자 대입연산자를 지원해야된다. 이를 만족해야 컴파일에 문제없이 동작한다. 즉, 템플릿이 제대로 동작하려면 몇 개의 인터페이스를 지원해야되고, 이 표현식들을 T가 지원해야하는 암시적 인터페이스라고 부른다. -
w
가 수반하고 있는 함수를 호출할 경우 호출을 성공시키기 위해 “템플릿 인스턴스화” 동작이 일어난다. 이러한 인스턴스화가 일어나는 시점이 컴파일 도중이다. 인스턴스화를 진행하는 함수 템플릿에 어떤 템플릿 매개변수가 들어가느냐에 따라서 호출되는 함수가 달라진다. 이를 가리켜 컴파일 타임 다형성이라고 부른다.
암시적 인터페이스 같은 경우, 어떤 소스코드를 참조 (즉, 함수의 시그니처 기반)하지 않고 유효표현식에 중점을 둔다는 점에서 명시적 인터페이스와 차이를 이룬다.
{
if (w.size() > 10 && w != someNastyWidget) {
...
}
}
암시적 인터페이스의 특징은 표현식을 기반으로 하고 있다는 점이다. 표현식만 만족하면 되는데, if
구문에 들어가는 bool
타입을 맞추도록 하면 된다. 즉, “w.size() > 10 && w != someNastyWidget” 해당 값이 bool
타입을 만족시킬 수 있게 호환성을 제공하면 된다는 점이다. 구체적으로 인터페이스가 어떤식으로 구축되어져 있어야한다고 명시하지 않는다는 것이 큰 장점이라고 보면 된다.
조금 더 구체적으로 예를들어, size()
같은 경우 10
이라는 int
값과 비교를 하고 있다. 그렇다고 해서 size()
인터페이스가 무조건 int
를 반환해야되느냐 그건아니다. operator>
연산자를 재정의해 int
타입을 받아서 bool
타입으로 반환하게 만들기만 하면 된다.
암시적 인터페이스를 구현할 때 주의할 점은 어떤 템플릿 안에서 어떤 객체를 사용하려고 할 때 그 템플릿에서 요구하는 암시적 인터페이스를 그 객체가 지원하지 않을 경우 사용이 불가능하다는 점을 주의해야한다. ( 컴파일이 아예 안될 것.. )
To Sum up
-
클래스 및 템플릿은 모두 인터페이스와 다형성을 지원한다
-
클래스의 경우, 인터페이스는 명시적이며 함수의 시그니처에 중점을 둔다. 다형성은 프로그램 실행 중 가상함수를 통해 나타난다.
-
템플릿 같은 경우, 인터페이스는 암시적이며, 유효 표현식에 기반을 두어 구성한다. 다형성은 컴파일 중에 템플릿 인스턴스화와 함수의 오버로딩 모호성 해결을 통해 나타난다.