Tag Archives: Template

Template Complete Guide – The Basics

함수 템플릿(Function Template)은 다양한 타입에 대한 기능적 동작을 제공한다. 즉 함수 템플릿은 타입의 다양성을 포괄하는 하나의 기능 구현을 가능케한다. 함수 템플릿이 적용된 함수는 일반 함수와 거의 유사한 모습을 갖지만, 일부 요소들은 구현시에 특정되지 않은채로 매개변수화된다.

실제로 컴파일 시에는 이러한 매겨변수화 된 부분이 하나의 독립된 매개변수화된 개체로 다루어지지 않는다. 해당 함수 템플릿을 사용하는 경우들을 분석하여 지정된 매개변수에 사용되는 모든 타입들이 분석되어 각 경우들이 별도로 컴파일 된다. 이처럼 템플릿 매개변수들을 실제 타입으로 구체화하여 사용하는 과정이 필요하며, 이 구체화 하는 과정을 인스턴스화(Instantiation)라고 한다. 템플릿 매개변수가 대응되어 사용될 타입에 따라, 사용자가 해당 타입으로 직접 함수를 구현한 것과 같은 내용이 인스턴스화 과정을 통해 컴파일 결과에 반영되는 것이다. 물론 함수 템플릿 안의 구현 내용에 따라서 매개변수에 대응될 수 없는 타입들이 존재할 수 있으며, 인스턴스화 시에 이러한 타입을 매개변수에 대응시키게 되면 컴파일 시점에서 오류가 발생한다.

이는 템플릿으로 구현된 부분이 두 번에 걸쳐 나뉘어 컴파일됨을 시사한다. 즉 템플릿으로 구현된 코드는 인스턴스화 시점을 경계로 나누어 생각할 수 있다.

  • 인스턴스화 전의 템플릿 코드는 잠정적으로 올바른 문법이라 간주된다. 템플릿 코드 이외의 문법적 오류들만이 검출가능하다.
  • 인스턴스화 시점에서 실제 템플릿 함수의 호출이 올바른지에 대한 구체적 검사가 수행되어, 템플릿 함수에서 지원하지 않는 함수 호출의 경우와 같은 오류가 검출된다.

결국 템플릿 함수를 구현된 시점에서는 오류가 없더라도, 템플릿 함수를 실제로 호출하는 경우가 추가됨에 따라 그에 따른 인스턴스화 과정에서의 오류가 발생할 가능성이 열려있는 것이다.

여기서 주의해야 할 점은 인자추론(Argument Deduction)과 관련된 특징이다. 템플릿 매개변수는 해당 함수를 실제로 호출하며 전달되는 매개변수(인자)에 대응된다. 즉 호출 시의 매개변수 타입으로부터 템플릿 매개변수가 추론된다. 그런데 문제는 템플릿 함수에 정의된 타입은 자동 형변환을 지원하지 않는다는 점이다. 예를들어 어떤 템플릿 함수 호출에 대하여 T로 매개변수화 된 타입에 int형과 double형을 동시에 인자로 전달할 경우, 일반적 함수호출과는 달리 컴파일러는 자동으로 이를 추론하여 처리해주지 않고 바로 오류를 표시한다. 이 예에서 나타나는 문제를 회피하기 위해서는 사용자가 사전에 두 가지 타입 중 보다 포괄적 타입으로 템플릿 함수를 인스턴스화 해야 한다. 이 외에도 리턴 타입을 추론해내는 것이 가능한지의 여부와 같은 이슈도 발생할 수 있으며, 이를 비롯한 모든 상황에서 템플릿 매개변수들의 추론이 불가능한 경우에는 각 매개변수들의 타입을 명시적으로 지정해주어야 한다.

템플릿 매개변수는 함수 뿐만 아니라 클래스에 걸쳐서도 적용될 수 있다. 클래스 템블릿(Class Template)은 해당 클래스의 전반에 걸친 매개변수화를 지원하며, 이 템플릿 매개변수는 클래스에 소속된 메소드와 변수 선언 및 정의 전반에 활용될 수 있다. 여기서 유념해야 할 부분은 매개변수에 대하여 실제 인스턴스화가 진행되는 부분은 전체 클래스 코드 중 ‘실제로 호출이 발생하는 메소드’에 국한된다는 점이다. 이를 통하여 컴파일 시간 및 그 출력물의 크기를 효율적으로 관리할 수 있다. 정적 메소드가 존재할 경우에는 새로운 타입의 인스턴스화가 일어난다면, 그 위치에 상관없이 정적 메소드는 각 타입에 대하여 인스턴스화된다.

그런데 사용자의 입장에서는 여러 타입에 대하여 동일한 클래스 템플릿을 사용하는 것 처럼 보이더라도, 사용자가 선택한 특정한 타입에 대해서는 해당 클래스의 알고리즘에 변경을 주는 편이 보다 효과적일 수 있다. 일반적인 경우에는 이러한 부분은 메소드의 오버로딩을 통하여 해결할 수 있겠지만, 템플릿의 경우는 매개변수화로 일반적 오버로딩 개념을 적용하기가 여의치 않다. 이에 대한 해결책이 바로 템플릿 특수화(Template Specialization)이다. 사용자가 클래스의 사용을 위하여 템플릿 매개변수를 확정하게 되는 시점에서, 만약 동일한 템플릿 클래스에 대한 특수화 코드가 존재하고 템플릿 파라미터의 타입이 특수화 된 매개변수의 타입과 동일하다면, 일반 템플릿 코드가 인스턴스화되는 것이 아니라 특수화로 정의된 타입의 클래스 코드에 따른 인스턴스화가 진행된다. 템플릿 매개변수가 여러개인 경우에는 필요한 매개변수에 대해서만 특수화를 적용할 수 있으며, 이러한 경우를 부분 특수화(Partial Specification)라 한다.

지금까지 이 글에서는 함수 템플릿이나 클래스 템플릿의 매개변수에 대해 ‘타입 결정자’의 측면에서 다루었다. 그런데 템플릿 매개변수는 타입 뿐만 아니라 비 타입 템플릿 매개변수(Nontype Template Parameters)의 사용을 지원한다. 특 템플릿의 인스턴스화 시점에서 결정된 매개변수는 타입이 아닌 실제 값을 가질 수 있으며, 이렇게 전달되는 값은 컴파일 시점에서 이미 결정되어 있으므로 배열의 생성 등의 동작에 사용될 수 있다. 당연하지만, 비 타임 템플릿 매개변수는 함수 템플릿과 클래스 템플릿에서 모두 적용할 수 있다.

참조: 『C++ Templates: The Complete Guide』, By David Vandevoorde, Nicolai M. Josuttis)