본문 바로가기
언어/C++

[C++ STL] 1-1. 템플릿 - 함수 템플릿(function template)

by 민-Zero 2020. 1. 11.

공부 내용을 정리하는 목적 이므로 참고용으로만 읽어 주시기 바랍니다.

틀린 부분에 대한 지적은 감사합니다.

1. STL(Standard Template Library) 이란?

지금까지 C++의 특징 중 하나인 OOP에 대해 정리했다. 이번에는 일반화 프로그래밍(generic programming)의 한축인 STL(Standard Template Library)에 대해 정리하고자 한다. 일반화 프로그래밍을 지원하는 대표적인 기능이 템플릿(template)이며 객체 지향 프로그래밍과 다르게 프로그램의 알고리즘을 중점적으로 다룬다

표준 템플릿 라이브러리인 STL은 알고리즘을 일반화한 표현을 제공하며 컴파일 타임 메커니즘을 사용하여 실행 시 성능 저하가 적고 표준이기 때문에 이식이 쉬워 코드의 재활용성을 높여준다.

STL은 다음과 같이 구성된 템플릿이 존재한다. 이러한 템플릿을 정리하기 위해 먼저 템플릿에 대해 정리하자.

  • 반복자(iterator)
  • 컨테이너(container)
  • 알고리즘(algorithm)

이러한 템플릿을 정리하기 위해 먼저 템플릿에 대해 정리하자.

 

2. 템플릿(template)

template 이란 '어떤 모양을 만들 때 사용하기 위한 틀' 이란 뜻이다. 언뜻 들으면 다양한 클래스의 상속을 위해 작성되는 추상 클래스와 비슷하다고 생각할 수 있다. 하지만 템플릿은 추상 클래스와는 다른 특징을 지니고 있다. 템플릿은 기능은 이미 결정되어 있지만 데이터 타입이 결정되어 있지 않다. 즉, 매개변수의 타입에 따라 함수나 클래스를 생성하는 메커니즘이다. 매개변수에 따라 타입이 표현되어 매개변수화 타입(parameterized type)이라고 불리기도 한다.

템플릿을 사용하면 타입마다 별도의 함수나 클래스를 생성하지 않고 하나의 함수나 클래스로 다양한 타입에서 동작할 수 있도록 해준다. 추상 클래스를 이용한 상속이 동일 매개변수에 대해 기능의 변경이나 확장이 가능했다면 템플릿은 동일한 기능을 다양한 매개변수에서 사용할 수 있게 일반화하는 것이다.

 

3. 함수 템플릿(function template)

함수 템플릿은 함수를 기반으로 만든 템플릿으로 함수를 일반화하는 것을 말한다. 즉, 함수의 기능을 정해두고 다른 타입에서 동작할 수 있도록 하나의 함수로 정의한다.

 

문법)

template<typename 타입이름1, typename 타입이름2, ...>

함수 원형{

    함수 기능

}

위와 같은 방법으로 템플릿을 통해 임의의 타입으로 정해진 함수를 생성한다. 함수를 호출할 때 매개변수에 타입을 전달하게 되면 컴파일러는 해당 타입에 맞는 함수를 생성해 동작시킨다.

 

예시를 통해 템플릿을 확인하자

만약 템플릿을 사용하지 않는다면 오버로딩을 통해 매개변수의 타입을 바꾼 동일한 함수를 사용할 수 있다.

하지만 템플릿을 사용하면 함수를 하나만 정의하고 함수를 호출할 수 있다. T라는 임의의 타입에 대해 반환값과 매개변수 타입을 T로 설정하여 함수를 동작한다고 생각하면 된다. 이와 같은 방법은 컴파일러가 알아서 데이터 타입을 정하도록 하기 때문에 의도하지 않은 데이터 타입으로 동작해 에러를 발생시킬 수 있다.

string을 사용하기 위해 #include <string>을 하였지만 c스타일 문자열로 입력되어 const char*가 계산되어 에러가 발생했다. 따라서 템플릿을 사용할 때 명시적으로 어떤 타입을 사용할지 알려주는 것이 좋다.

함수명 옆의 <>에 사용하고자 하는 데이터 타입을 사용하여 template의 임의의 데이터 타입 typename을 정의해주면 된다.

단일 타입뿐만 아니라 다양한 타입에 대해서도 사용 가능하다. 또한 여러 타입에 대해 사용할 경우 <> 안의 명시해주는 타입의 순서에 따라 template정의에 사용한 임의의 데이터 타입 T1 T2가 결정되므로 주의하자.

 

3. 특수화(specialization)

생성한 템플릿은 타입에 대해 처음 호출될 때 컴파일러가 해당 타입에 대한 인스턴스를 생성한다. 이때 생성된 인스턴스는 해당 타입에 대한 특수화된 함수 템플릿이다. 함수 템플릿에 대해 해당 타입이 사용될 때마다 이 인스턴스가 호출되게 된다.

이때 특정 타입에 대해 명시적 특수화를 진행하여 따로 기능을 정의하게 되면 컴파일러가 호출된 함수에 대한 인스턴스를 찾다가 특수화된 정의를 발견하면 더는 템플릿을 찾지 않고 해당 정의를 사용한다. 따라서 특수한 자료형에 대해서는 다른 동작을 진행할 수 있게 된다.

 

문법)

template<>

반환타입 함수명<특정 타입>(특정 타입){

    함수 기능

}

tmplate에 typename을 작성하지 않고 명시적으로 특정 데이터 타입에 대해 함수를 정의하면 된다.

 

예시를 통해 확인해보면

매개변수로 전달받은 출력해주는 ShowInfo라는 함수 템플릿에 double, int형의 인스턴스에 대해서는 특수화를 진행하여 다른 동작을 수행하게 한 모습니다. 따라서 함수가 호출될 때 해당 타입의 인수가 전달되면 특수화시킨 동작을 진행하는 것을 확인할 수 있다. 

댓글