2009.04.06 13:47 책 정리/C++ Template

{
이번 장은 "1부, 템플릿 기본"에 속해 있다.

함수 템플릿이 무엇인가?
 다양한 데이터형에 호출 되는 함수이다.

어떻게 함수 템플릿을 정의 하는가?
 다음 처럼 정의 할 수 있다.


우선 fuction family 는 함수 템플릿을 가리키는 말인 것을 밝힌다. const 의 사용 법은 1장에서 말했던 규칙 데로 사용 됬다. 본론으로 들어와서 max 함수 템플릿은 a 와 b 중 큰 값을 리턴하며, 이때 a와 b의 타입은 아직 정해지지 않았으며, 타입을 typename T로 파라미터화 했다. 이 typename T를 템플릿 파라미터 이라고 이제부터 부른다.

템플릿 파라미터는 어떻게 정의 하는가?
template < 템플릿 파라미터 > 으로 정의 하며, 위의 예제에선 typename T가 파라미터이다. 즉, T가 파라미터가 아니라 "typename T" 가 파라미터 이며, 여러개의 파라미터는 ",(쉼표)" 로 구분 지어 정의 할 수 있다. 그리고 이런 여러개의 파라미터들을 파라미터 목록이라고 한다.

꼭 T를 사용해야 하는가?
 아니다. 일반적으로 타입을 파라미터화 할 때는 T를 쓴다.

typename 말고도 class가 있던데?
 역사적으로 class가 나온 뒤에 typename 이 나왔기 때문에 class 를 사용해도 된다. 하지만 class를 사용하면 잘못 이해 될 수 있기 때문에, typename을 쓰는게 좋다고 필자는 말한다.(나 또한 typename이 좋을 것이라고 생각한다.)

typename 과 class가 어떻게 잘못 이해 될 수 있는가?
 class T 라고 했을 때, class형에 대해서만 파라미터화 될 수 있다고 착각 할 수 있다. 즉, int 나 struct 등에 대한 타입은 되지 않을 것이라다 라고 이해 될 수 있다.

함수 템플릿은 어떻게 호출 하는가?


위의 프로그램에서 max() 는 템플릿 함수로 정의하고, main() 내부에서 4번의 max 함수를 호출 했으며, 전혀 다른 타입들로 max()를 호출 했다. 위의 함수 사용방법은 일반 함수와 똑같다. ( ::max()라고 한 이유는 C++의 이름검색의 모호성 떄문이다. )

알겠는데, 어떻게 각각 호출 될 수 있는가?
 최초 컴파일러가 코드를 분석 할때 max가 템플릿 함수임을 파악한다. 그리고 max()가 쓰인 자리에서 타입을 유추한다. 그리고 그 타입과 가장 적절한 max()를 코드화 시킨 후에, 컴파일 한다. 이 과정을 max()가 있는 모든 자리에서 수행한다.

잘 모르겠다. 그러니까 몇개의 max가 어떻게 코드화 되는지 코드로 보여 달라.



max 함수 템플릿은 위의 4개의 max 함수로 코드화 되고, 컴파일 되는 것이다.

여기서 알아두면 내용 이해에 좋을 만한 용어를 설명해 달라.
템플릿 파라미터는 위에서 설명했으니 패스 한다. 템플릿 파라미터를 실제 데이터형으로 바꾸는 작업을 "인스턴스화:instantiation"이라고 부른다. 인스턴스화가 끝나면 템플릿의 인스턴스:instance(코드)가 생긴다. 이런 인스턴스는 코드가 사용 될 때, 발생한다.

인스턴스화? 인스턴스? 무슨 말인가?
 인스턴스화는 파라미터가 데이터형으로 바뀌는 것을 말하는 것이고, 인스턴스는 템플릿 함수의 실체가 생기는 것을 말한다.

이게 중요한가?
 뭐 별로 중요하지 않다. 단지 책을 더 쉽게 읽기 위해서 집고 넘어 가는 것 뿐이다.

인스턴스화는 언제 일어 나는가?
 위에 정리했지 않는가? 함수가 사용 될떄 컴파일러가 인스턴스화를 한다.

인스턴스는 언제 일어 나는가?
 인스턴스화를 거친 후, 인스턴스가 된다.

이게 중요한가?
 중요하지 않다. 책을 읽기 위한 수단일 뿐이다. 음 중요한거 같기도 하다. 인스턴스와 인스턴스화의 차이점은 중요하지 않으나, 인스턴스화 되는 시점은 분명 중요하다.

왜 중요한가?
 일반적인 함수는 선언:declaration 과 정의:definition 을 파일로 분리시켜서 컴파일 할 수 있다. 이는 컴파일 시간을 줄이는 대표적인 기술이다. 하지만 함수 템플릿(클래스 템플스도 마찬가지)의 경우 코드가 사용 된 시점에 코드가 인스턴스화 되어 인스턴스 되기 때문에, 사용 된 시점에 그 정의:definition 까지 다 컴파일러가 볼 수 있어야 한다. 즉, 템플릿을 사용 하면, 선언:declaration 과 정의:definition 을 분리하기가 무척 불편하다.

분리시키는게 왜 불편한가?
 export 키워드를 사용 하며 되지만, exprot 키워드를 지원하는 컴파일러가 별로 없기 때문에 불편하다.

현재(2009.04.05)까지 가장 좋은 방법은 무엇인가?
 분리하지 않고, 한 파일에 선언과 정의 하는 방법이 가장 좋다.

알겠다. 인스턴스화에 대해서 좀 더 자세한 설명은 없는가?
 인스턴스화는 템플릿 파라미터가 실제 대이터형으로 바꾸는 작업이라 했다. 함수 템플릿의 경우, 컴파일러가 인자로 부터 타입을 추론한다. 물론 함수 템플릿이 사용 될 때이다. 이때 자동 형 변환은 일어나지 않는다.

음, 다 이해하겠는데, 자동 형 변환은 무엇을 뜻하는가?
 자동 형 변환은, int형 값 1과 short형 값 1이 있다고 했을 때, short의 1이 int의 1로 특정 연산을 통해서 자동으로 바뀌는 것을 말한다. 특정 연산은 사칙연산이나, 함수의 인자값 전달 등을 뜻한다.

자동 형 변환이 일어나지 않는다는게 무슨 말인가?
 즉, 아래와 같이 사용 하지 못한다는 것을 뜻한다.


저런 경우 어떻게 해야지만, 컴파일 되는가?
 3가지 방법이 있다. 각각 예제를 보자.
1. max에 들어갈 인자를 하나의 타입으로 통일 시키는 방법
예제코드

2. max에 들어갈 인자를 명시하는 방법
예제코드

3. 템플릿 파라미터가 다른 데이터형을 갖을 수 있도록 max함수를 바꾸는 방법
예제코드

1, 2 방법은 이해가 되는데, 다른 템플릿 파라미터를 두는건 첫번째 T1을 강제 형변환 될 수 있지 않는가?
맞다. 그것이 바로 단점이고, 문제점이다. 바로 자동형변환 되어야만 할 때는, 함수 안에서 만든 임시변수를 레퍼런스:reference 형태로 반환되어 문제가 생길 수 있다는 것이다.


함수 템플릿의 호출 방법에 대해서 좀 더 알려 줄 수 없나?
 함수 템플릿은 두가지의 호출 형태를 가질 수 있다. 첫번째는 위에서 했던 일반 함수와 동일한 방법이고, 두번째는  명시적으로 사용 하는 방법이 있다.

두번째로 명시적으로 사용하는 방법을 알려 줄 수 없나?
 자동 형 변환 예제 중 두번째가 명시적으로 호출 하는 방법이다.

두 방법이 존재 하는 이유는 무엇인가?
 컴파일러가 함수 템플릿에 들어가는 인자를 통해서 템플릿 파라미터를 추론 할 수 있다면, 일반 함수 호출 방법으로 그냥 사용함으로써, 편하게 사용 할수 있음을 제공 해주는 이유와, 인자를 통해서 템플릿 파라미터를 추론할 수 없다면, 명시적으로 사용 할 수 있게끔 하기 위해서이다.
 
음? 인자 추론은 알겠는데, 명시적으로 사용 하는 예가 있는가?
 boost::bind 가 그 대표적인 예가 되지 않을까 한다. 가끔 컴파일러가 추론 할 수 없을 때 리턴 타입을 명시해 줘야지만 컴파일 되는 경우가 있기 때문이다.

호출 호출 하는까 함수 템플릿을 오버로딩 할수 있는가?
 할 수 있다.

그 방법을 알려 줄 수 있는가?
 일반 함수처럼, 같은 이름을 가지는 함수를 만들면 된다.

예제코드를 줄 수 있는가?


음? 에러가 있는데?
 그건 무시하라. 조심하라는 취지에서 그냥 남겨 둔 것이다.

왜 함수 템플릿이 호출되지 않고, 일반 함수가 호출 되는가?
 우선 순위가 함수 템플릿보다 일반 함수가 더 높기 때문이다.

미묘하다. 더 자세히 알려 줄 수 있는가?
 함수 템플릿 때문에, 컴파일러는 가장 적당한 함수를 만든다. 그리고 컴파일러는 가장 적당한 함수를 호출 한다. 여기서 몇가지 과정이 더 숨어 있는데, 컴파일러가 만든 가장 적당한 함수를 "함수 템플릿 테이블"에 올려 두고, 일반 함수가 없는지도 찾는다. 이때 컴파일러가 적당한 일반 함수를 찾았다면 "일반 함수 테이블"에 올려 둔다.

이때 일반 함수 테이블에 아무것도 없다면 "함수 템플릿 테이블"의 함수를 호출하고, 있다면 "일반 하수 테이블"의 함수를 호출 한다.

그래도 미묘한데?
 그래서 함수 템플릿이 오버로딩은 잘 사용하지 않는다. ㅋㅋ

요약해 줄 수 있는가?
1. 함수 템플릿은 다양한 템플릿 인자에 대한 함수군을 정의 한 것이다.
2. 템플릿 인자를 건네면, 함수 템플릿은 인자 추론을 통하여 인스턴스화가 일어 난다.
3. 템플릿 파라미터를 명시적으로 정할 수 있다.
4. 오버로딩한 함수 템플릿을 호출 할려면, 그 오버로딩 버전이 다 보여야만 한다.
}


posted by 농사를 짓는 게임 프로그래머 최익필

댓글을 달아 주세요