티스토리 뷰
C++17 함수 템플릿 #001 함수 템플릿 (Function Templates)
함수 템플릿은 다양한 타입(type)에 대해 호출될 수 있는 어떠한 함수적인 동작을 제공한다. 함수의 일부 요소가 파라미터화(parameterized)되어 정해지지 않았다는 점을 제외하면 일반적인 함수와 거의 같다.
다음은 두 값 중에서 큰 값을 반환하는 함수 템플릿이다.
/* max1.hpp */
template <typename T>
T max(T a, T b) {
return b < a ? a : b;
}
이 함수 템플릿의 정의는 함수 파라미터(parameter)로 전달된 a와 b라는 두 값 중에서 큰 값을 나타내는 함수들의 모임을 나타낸다. 함수 파라미터의 타입은 템플릿 파라미터(template parameter) T로 아직 정해지지 않은 상태이다.
템플릿 파라미터는 다음과 값은 문법을 사용해서 명시되어야 한다.
template < /* comma-separated-list-of-parameters */ >
이번 예제에서 파라미터 목록(parameter list)는 typename T이다. 타입 파라미터는 typename으로 도입한다. 이러한 타입 파라미터가 C++에서 가장 흔하게 사용되는 템플릿 파라미터이지만 다른 파라미터도 사용할 수 있다.
역사적인 이유로 타입 파라미터를 정의할 때 typename 대신에 class를 사용할 수 있다. typename이라는 키워드(keyword)가 C++98 표준을 만드는 중에 상당히 늦게 도입된 편이고, 그 이전에는 타입 파라미터를 도입할 때 class라는 키워드를 사용했기 때문이다.
나중에 소개할 템플릿 템플릿 파라미터(template template parameter)에서 반드시 class를 사용해야 하는 경우가 있었지만 C++17부터는 템플릿에 대해서는 typename과 class는 완전히 동등한 키워드로 사용될 수 있다.
/* max1.cpp */
#include <iostream>
#include <string>
#include "max1.hpp"
int main() {
int i = 42;
std::cout << "max(7, i): " << ::max(7, i) << '\n';
double f1 = 3.4;
double f2 = -6.7;
std::cout << "max(f1, f2): " << ::max(f1, f2) << '\n';
std::string s1 = "mathematics";
std::string s2 = "math";
std::cout << "max(s1, s2): " << ::max(s1, s2) << '\n';
}
max(7, i): 42
max(f1, f2): 3.4
max(s1, s2): mathematics
이 프로그램에서 max()는 세 번 호출되며 처음에는 int 두개가 두번째는 double 두개가 세번째는 std::string 두개가 인자로 넘겨진다.
※ ::을 이용해서 전역 이름 공간(global namespace)에서 max() 템플릿을 찾도록 하였다.
일반적으로 템플릿이 어떠한 형식이라도 다룰 수 있는 하나의 실체로 컴파일(compile)되지는 않는다. 그 대신 템플릿이 사용될 때마다 템플릿으로 각 타입에 맞는 실체를 만든다. 따라서 max()는 세 가지 형식에 맞추어 각각 컴파일 된다.
템플릿 파라미터를 실제 타입으로 바꾸는 것을 인스턴스화(instantiation)이라고 한다. 이를 통해 템플릿의 인스턴스(instance)가 생성된다.
※ 객체 지향 프로그래밍의 인스턴스는 클래스(class)의 실제 객체(object)를 의미한다. 하지만 이 글은 템플릿에 관한 것이기에 특별한 언급이 없으면 인스턴스는 템플릿의 사용을 나타내는 것으로 하자.
참고로 void도 유효한 템플릿 인자(argument)이므로 그 결과로 생성되는 코드도 유효하다.
template <typename T>
void foo(T *){};
void *p = nullptr;
foo(p) // OK: void foo(void *)
함수 템플릿 내부에서 사용된 모든 연산자를 지원하지 않는 타입에 대해서 템플릿을 인스턴스화하면 컴파일 오류가 발생한다. 예를들어 다음 예시를 살펴보자.
std::complex<float> c1, c2; // Doesn't provide operator<!
/* ... */
::max(c1, c2); // ERROR at compile time!
이를 위해 템플릿은 두 단계에 거쳐서 컴파일(번역)한다.
<-- 작성중 -->
'Computer Science > C++' 카테고리의 다른 글
C언어와 C++17의 차이점 (0) | 2020.02.17 |
---|---|
C++ Template Metaprogramming #00 소개 (0) | 2020.02.14 |