개요
지금까지 함수, 클래스 템플릿의 파라미터는 데이터형만 있는 것처럼 정리하였으나, 일반값도 있다. 이번 장은 데이터 형이 아닌 템플릿 파라미터란 무엇이고, 어떻게 사용하며, 주의해야 할 사항에 대해서 정리 되어 있다.

본문
데이터형이 아닌 템플릿 파라미터는 무엇인가?
상수로 평가되는 모든 값들이다. 하지만 예외적으로, 부동소수점(float, double) 상수와 문자열 상수(char *, wchar_t *)는 템플릿 파라미터로 사용 할 수 없다. 그래서 코드짜면 다음과 같이 코딩 할 수 있다.

여기서 보듯이 첫번째 템플릿 파라미터는 데이터형이지만, 두번째 파라미터는 인트형 값을 받아 들이고 있다. 멤버 함수는 일전에 설명했던 클래스 템플릿 멤버 함수 정의하는 방법과 똑같다. 기본 템플릿 파라미터를 정할 수 도 있는데, 이 역시도 똑같다.

왜 부동소수점과 문자열은 데이터형이 아닌 템플릿 파라미터로 올 수 없는가?
부동소수점은 역사적 배경 때문이라 하고, 문자열 상수는 다음의 이유에서이다.

이 코드는 컴파일이 되지 않는다. 왜냐하면 "hello"의 반환값은 엄연히 임시 포인터 변수 이기 때문인데, 혹여나 char const * const str = "hello" 될수 있겠다고 생각하지만, 마찬가지로 str은 "hello"를 가리키는 포인터 변수인 것은 변함에 없다. 변수는 템플릿이 요구하는 상수가 아니므로 컴파일이 되지 않는 것이다.

어떻게 하면, 문자열을 템플릿 파라미터로 전달 할 수 있는가?
"hello"를 가리키지 않고 'h', 'e', 'l', 'l', 'o' 자체를 저장한 상수의 주소를 넘기면 된다. 눈치 빠른 사람은 알겠지만, 바로 배열이다. 배열의 이름은 누구도 가리키지 못하도록 이미 결정되어 버린 주소이다. 그러므로 다음과 같이 코드를 바꾸면 컴파일이 되는 것을 확인 할 수 있을 것이다.

이것을 잘만 응용하면, 잼있는 것을 많이 할 수 있다. ps, 객체의 포인터를 저장한 변수가 아닌, 객체의 주소를 넘겨야 한다는 것이 키포인트이다.

데이터형이 아닌 템플릿 파라미터를 어떻게 사용 하는가?

사용 방법도 똑같다. 위에선 클래스 템플릿만 설명했지만, 함수 템플릿도 똑같으므로, 그러려니 하고 생략한다. 함수 템플릿에서 주의해야 할 사항이 하나 있는데, 함수 템플릿 인스턴스는 앞에서도 설명했듯이 "오버로딩 함수들의 집함에 대한 이름일 뿐" 이다. 템플릿 파라미터로 함수 템플릿 인스턴스를 넘기게 될 경우 컴파일 에러를 뱉어 낸다. 다음 코드를 보자.

그러므로 19번째 자리에서 컴파일 에러가 난다. 왜냐하면 addValue<int, 5> 는 transform 3번째 템플릿 파라미터 _Fn1에서 추론되어지지 않는게 현재의 C++ 표준이기 때문이다. 하지만, VC2005, 2008 에선 잘 된다. 많은 컴파일러에서 컴파일 되게 하고 싶다면 (int *)(int const&)) addValue<int, 5> 이렇게 함수를 전달해야 한다.

이상~



  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 라이프코리아트위터 공유하기
  • shared
  • 카카오스토리 공유하기

댓글을 달아 주세요

">
  1. Favicon of http://kuaaan.tistory.com kuaaan
    2009.05.17 17:26

    저 역시 문자열 버퍼(TCHAR[50])를 템플릿에 집어넣지 못해 고생한 기억이 있습니다.
    결국 TCHAR Array를 Entry로 가지는 구조체를 하나 선언하고 그 구조체를 템플릿에 집어넣는 방식으로 해결한 기억이 있는데요... 다른 곳을 포인팅할 여지가 없는 완전한 상수만이 템플릿에 들어갈 수 있다는 건가요... 알듯말듯 하군요.... ^^;;;

  2. ㅂㅂㅂㅂ
    2009.06.02 07:20

    흠.. 비타입 인수라고 배운 기능이로군요.. 정수형 넘기는 것 보고 신기해 했었는데..
    그나저나 문자열을 던져주는 것은.. 예전부터 생각은 해봤지만..
    저렇게 배열로만 넘겨야 한다는건 처음 알았네요..