std::vector를 매개변수로 하는 함수
std::vector는 다양한 타입의 데이터를 담을 수 있는 컨테이너입니다.
이 컨테이너는 사용자가 원한다면, 매우 많은 원소를 저장할 수 있기 때문에, 함수에서 사용하려면 값에 의한 전달( call by value )이 아니라 참조에 의한 전달( call by reference ) 방식을 사용해야 합니다.
#include <iostream>
#include <vector>
// vector를 매개변수로 하는 함수
void printData( const std::vector<int>& vec){
for( auto i : vec){
std::cout << i << " ";
}
std::cout << '\n';
}
int main(){
std::vector<int> vec{ 1, 2, 3, 4, 5 };
printData( vec );
}
▼출력
1 2 3 4 5
그런데, 다양한 타입을 저장할 수 있는 템플릿 클래스의 객체를 매개변수로 사용하면서, 함수 자체는 고정된 타입의 인자만을 수용할 수 있도록 작성하는 것은 스스로 코드의 가능성을 제한하는 일이 될 것입니다.
그러므로 위와 같이, 템플릿을 사용하는 타입을 매개변수로 가진 함수는 템플릿 함수로 구현해야 합니다.
그리고, 이렇게 하는 데는 두 가지 방법이 있습니다.
vector의 데이터 타입을 지정하는 함수 템플릿
이 방식은 함수 템플릿 매개변수( template parameter ) T가 std::vector가 저장하는 데이터 타입을 지정하는 함수 템플릿을 작성하는 것입니다.
template <typename T >
void printData( const std::vector<T>& vec){
for( auto x : vec){
std::cout << x << " ";
}
std::cout << '\n';
}
int main(){
std::vector<int> vec{ 1, 2, 3, 4, 5 };
printData( vec );
std::vector<double> vec2{ 1.1, 2.2, 3.3, 4.4 };
printData( vec2);
}
▼출력
1 2 3 4 5
1.1 2.2 3.3 4.4
하나의 함수 템플릿을 통해서, int와 double 타입의 데이터들을 동일한 방식으로 처리할 수 있게 되었습니다.
만약, 특정한 데이터 타입에 대해서, 다른 타입과 다른 기능을 수행하는 함수를 작성하고 싶다면, 위 함수 템플릿의 특수화( template specialization )된 함수를 구현할 수도 있습니다.
template<> // 함수 템플릿의 특수화
void printData( const std::vector<double>& vec){
// double 데이터를 과학적 표기법으로 표시
std::cout << std::scientific;
for( auto x : vec){
std::cout << x << " ";
}
std::cout << '\n';
}
▼출력
1 2 3 4 5
1.100000e+00 2.200000e+00 3.300000e+00 4.400000e+00
이 특수화된 템플릿 함수는, 기본 템플릿에서 인스턴스화된 함수가 있더라도 컴파일러에 의해 우선적으로 선택되고 사용됩니다.
다양한 타입의 매개변수를 사용할 수 있는 함수 템플릿
이 방식은 위의 방식보다 더 범용적인 타입을 매개변수로 사용할 수 있도록 하는 함수 템플릿입니다.
template <typename T > // 다양한 타입의 매개변수가 가능한 함수 템플릿
void printData( const T& vec){
for( auto x : vec){
std::cout << x << " ";
}
std::cout << '\n';
}
이 방식의 장점은 인자가 std::vector 타입이 아니어도, 이 함수 템플릿을 이용할 수 있다는 것입니다.
특히, std::array와 std::string 같이 사용법이 유사한 템플릿 클래스 타입을 인자로 전달할 수 있다는 강점이 있습니다.
#include <iostream>
#include <vector>
#include <array>
int main(){
std::vector<int> vec{ 1, 2, 3, 4, 5 };
printData( vec );
std::vector<double> vec2{ 1.1, 2.2, 3.3, 4.4 };
printData( vec2);
std::array<int, 5 > arr{ 1, 2, 3, 4, 5}; // 배열도 함수 템플릿을 이용
printData( arr);
std::string str{ "This is a string"};
printData( str);
}
▼출력
1 2 3 4 5
1.1 2.2 3.3 4.4
1 2 3 4 5
T h i s i s a s t r i n g
하지만, std::vector 클래스만이 가진 기능( 예를 들면, emplace, emplace_back )을 이용한 코드는 작성할 수 없습니다.
정리
- 템플릿을 사용하는 타입을 매개변수로 하는 함수를 작성할 때는, 함수 템플릿( function template )을 우선적으로 고려하는 것이 타당합니다.
'표준 라이브러리' 카테고리의 다른 글
| [C++] 호출 가능한 객체를 저장하는 std::function (0) | 2025.03.17 |
|---|---|
| [C++] 주어진 원소들에 함수를 적용하는 std::for_each (0) | 2025.03.12 |
| [C++] 입력된 원소들을 차례로 변환하는 std::transform (0) | 2025.03.11 |
| [C++] 배열, 컨테이너, 사용자 정의 데이터를 정렬하기 위한 std::sort (0) | 2025.03.10 |
| [C++] 구분자까지 문자열을 입력받는 std::getline 함수 (0) | 2025.03.03 |
