18. 템플릿의 다형적 능력
다형성이란 일반 표기법 하나만으로 다양하고 구체적인 행위를 연결시키는 능력으로, C++에서는 클래스 상속과 가상 함수를 통해 지원하고 있는 객체지향 프로그래밍 패러다임의 주춧돌이 다형성입니다.
18.1 동적 다형성
역사적으로 C++는 가상 함수와 함께 상속을 지원하는 방식으로 다형성을 지원하였습니다. 여기서 다형성 설계의 기술은 객체형들 사이에서 공통된 기능을 식별하고, 그 기능을 이들을 공통 기본 클래스에서 가상 함수 인터페이스로 선언하는 것입니다. 이는 실행 시간에서 함수 호출을 디스패치할 때 실제로 어떤 객체의 가상함수가 호출돼야 하는가를 동적으로 결정합니다. 이러한 동적 다형성 중 가장 큰 매력은 다양한 객체를 모아 처리할 수 있는 능력입니다.
18.2 정적 다형성
템플릿도 다형성을 구현하는 데 사용도리 수 있지만, 이는 기본 클래스의 공통 행위가 아닌 응용의 다른 모습이 공통 문법을 사용해 연산을 지원해야한다는 암묵적 합의에 기반을 둡니다. 이는 공통 기본 클래스가 아닌 템플릿 파라미터를 사용하여 정하는데, 이는 실행 시간이 아닌 컴파일 시간에 정해지게 됩니다. 하지만 이는 서로 다른 객체의 모음이기에 쉽게 관리하기 어렵습니다. 또한 모든 형식은 컴파일 시에 결정돼어야 합니다. 대신에 확장시키기 쉬우며, 포인터에 국한 시킬 필요가 없기에 성능이나 형식 안정성 면은 더욱 나아졌습니다.
18.3 동적과 정적 다형성
두 종류의 다형성을 분류 비교 해봅시다
용어
- 상속에 의해 구현되는 다형성은 한정돼 있으며 동적입니다.
- 한정된이란 다형적 동작에 참여하는 형식의 인터페이스가 공통 기반 클래스의 설계에서부터 미리 결정됐다는 뜻입니다
- 동적이란 말은 실행시간에 인터페이스의 바인딩이 결정된다는 뜻입니다
- 템플릿으로 구현된 다형성은 한정되지 않았으며 정적입니다
- 한정되지 않았다는 것은 다형성 동작에 참여하는 형식의 인터페이스가 먼저 정해지지 않았다는 뜻입니다
- 정적이라는 말은 인터페이스의 바인딩이 컴파일 시에 결정된다는 뜻입니다.
장점과 약점
동적 다형성의 장점은 다음과 같습니다
- 서로 다른 객체의 모음을 우아하게 처리할 수 있습니다.
- 실행 코드 크기가 잠재적으로 작습니다(템플릿에서 다양한 형식을 처리하려면 서로 다른 템플릿 인스턴스 생성됨)
- 코드를 완전히 컴파일할 수있어, 소스코드를 배포할 필요가 없습니다
정적 다형성의 장점은 다음과 같습니다.
- 내장 형식의 모음이 쉽게 구현됩니다. 좀 더 일반적으로 인스턴스 공통성이 공통 기반 클래스를 거쳐 표현될 필요가 없습니다.
- 생성된 코드가 잠재적으로 더 빠릅니다
- 애플리케이션에서 일부만 사용될 경우 부분 인터페이스만을 제공하는 실제 객체도 사용될 수 있습니다.
정적 다형성은 모든 바인딩을 컴파일 시에 검사하여 동적 다형성에 비해 형식 안전성이 높다고 알려져 있습니다.
물론 두 종류의 다형성을 결합시킬 수 있으며 이는 21장에서 알아보도록 하겠습니다.
18.4 개념 사용
템플릿으로 정적 다형성을 지원할 때는 인터페이스의 바인딩이 해당 템플릿을 인스턴스화 할 때 결정된다는 점 떄문에 반대하는 의견도 존재합니다. 이는 프로그램 간의 공통 인터페이스가 없다는 것을 의미하기 때문입니다. 이는 유효하지 않을 때 어려운 오류 메세지가 발생하거나 원치 않은 동작을 수행할 수도 있습니다. 그렇기에 이를 이전에 검사하는 개념(concepts)를 도입하였습니다. 이는 C++20에서 부터 사용 가능합니다.
template<typename T>
concept GeoObj = requires(T x) {
{ x.draw() } -> void;
{ x.center_of_gravity() } -> Coord;
//...
};
위와 같이 concept 키워드를 사용하여 명시하고, 이를 requires 절을 통해 다른 곳에서 확인할 수 있도록 합니다.
18.5 설계 패턴의 새로운 형태
정적 다형성이라는 새로운 형태가 등장하면서 브리지 패턴과 같이 인터페이스의 다양한 구현들 사이를 오갈 수 있는 패턴이 태어났습니다.
18.6 일반 프로그래밍
정적 다형성은 일반 프로그래밍이라는 개념을 지지하지만, 이는 합의되지 않은 개념입니다. C++에서 일반 프로그래밍이란 템플릿을 이용한 프로그램을 일컫곤 하는데, 이는 템플릿이 다수의 유용한 조합을 가능하게 하는 목적을 가진 프레임워크에서 설계돼야 합니다. 이의 가장 큰 결과물은 STL입니다. 알고리즘과 컨테이너 모두 템플릿으로 iterator와 같이 다양한 기능이 추상 개념으로 구현되어 있고, 이는 안은 모르더라도 쉽게 사용할 수 있도록 만들어져 있습니다.