C++ 초급 - 9. 템플릿 기초 (1 - 함수 템플릿 (Function Template))

2025. 2. 22. 17:00프로그래밍 언어/C++

📌 9. 템플릿 기초

C++의 템플릿(Template)일반화 프로그래밍(Generic Programming)을 가능하게 하며, 데이터 타입에 의존하지 않는 코드를 작성할 수 있도록 해준다.
템플릿을 활용하면 재사용성이 높은 코드를 작성할 수 있으며, 컴파일 타임에 타입을 결정하여 최적화된 실행 성능을 제공한다.


📌 9.1 함수 템플릿 (Function Template)

C++의 함수 템플릿(Function Template)을 사용하면 데이터 타입에 의존하지 않는 함수를 작성할 수 있다.
이를 통해 코드 중복을 줄이고, 보다 범용적인 로직을 구현 가능하며, 컴파일 시점에 타입이 결정되어 최적화된 성능을 제공한다.


📌 1. 템플릿 함수의 기본 개념 (template<typename T>)

🔹 (1) 함수 템플릿이란?

  • 템플릿(Template)컴파일 시점에 타입을 결정하는 일반화된 함수 또는 클래스를 의미한다.
  • template<typename T> 또는 template<class T>를 사용하여 정의함.
  • 컴파일러가 T에 해당하는 타입을 추론하여 특정 타입의 함수로 변환한다.

💡 기본 문법

template<typename T>
T 함수이름(T 매개변수) {
    // 함수 구현
}

💡 예제: 두 값 중 최댓값을 반환하는 함수 템플릿

#include <iostream>

// 함수 템플릿 정의
template<typename T>
T getMax(T a, T b) {
    return (a > b) ? a : b;
}

int main() {
    std::cout << "큰 값: " << getMax(10, 20) << std::endl;      // 정수형 템플릿 호출
    std::cout << "큰 값: " << getMax(5.7, 3.3) << std::endl;    // 실수형 템플릿 호출
    std::cout << "큰 값: " << getMax('A', 'Z') << std::endl;    // 문자형 템플릿 호출

    return 0;
}

🔹 출력 결과

큰 값: 20
큰 값: 5.7
큰 값: Z

💡 설명

  • template<typename T>를 사용하여 데이터 타입을 일반화함.
  • getMax(10, 20); → getMax<int>(10, 20);로 변환됨 (정수형 버전).
  • getMax(5.7, 3.3); → getMax<double>(5.7, 3.3);로 변환됨 (실수형 버전).
  • getMax('A', 'Z'); → getMax<char>('A', 'Z');로 변환됨 (문자형 버전).

📌 2. 템플릿 함수 선언 및 구현 방법

🔹 (1) 템플릿 함수 선언

  • 템플릿 함수를 선언할 때는 template<typename T>를 사용하여 타입을 일반화한다.
  • T는 임의의 타입을 의미하며, 함수가 호출될 때 자동으로 타입이 결정됨.

💡 기본 문법

template<typename T>
T 함수이름(T 매개변수1, T 매개변수2);

🔹 (2) 템플릿 함수 정의

  • 템플릿 함수를 정의할 때는 일반 함수와 유사하나, template<typename T>를 앞에 붙여야 함.

💡 예제: 두 개의 값을 더하는 템플릿 함수

#include <iostream>

// 템플릿 함수 선언 및 정의
template<typename T>
T add(T a, T b) {
    return a + b;
}

int main() {
    std::cout << "정수 합: " << add(3, 7) << std::endl;     // 10
    std::cout << "실수 합: " << add(2.5, 1.2) << std::endl; // 3.7
    return 0;
}

🔹 출력 결과

정수 합: 10
실수 합: 3.7

💡 설명

  • add(3, 7); → add<int>(3, 7);로 변환됨.
  • add(2.5, 1.2); → add<double>(2.5, 1.2);로 변환됨.

📌 3. 템플릿 함수 호출 방식 (함수 인자 타입 추론)

🔹 (1) 타입 추론 방식

  • 템플릿 함수는 매개변수의 타입을 기반으로 자동으로 타입을 추론한다.
  • 명시적으로 타입을 지정할 수도 있음.

💡 예제: 자동 타입 추론 vs 명시적 타입 지정

#include <iostream>

template<typename T>
T multiply(T a, T b) {
    return a * b;
}

int main() {
    std::cout << multiply(3, 4) << std::endl;     // ✅ 자동 타입 추론 (int)
    std::cout << multiply<double>(3, 4) << std::endl; // ✅ 명시적 타입 지정 (double)
    return 0;
}

🔹 출력 결과

12
12.0

📌 4. 템플릿 특수화 (Template Specialization)

🔹 (1) 특정 타입에 대한 맞춤 구현

  • 템플릿을 사용할 때, 특정 타입에 대해서 특수한 동작을 정의하고 싶을 때 템플릿 특수화(Template Specialization)를 사용한다.

💡 예제: char* 타입의 특수화

#include <iostream>

template<typename T>
T getMin(T a, T b) { return (a < b) ? a : b; }

// 특수화 (char* 타입에 대한 동작 정의)
template<>
const char* getMin<const char*>(const char* a, const char* b) {
    return (std::strcmp(a, b) < 0) ? a : b;
}

int main() {
    std::cout << "최소값: " << getMin(3, 7) << std::endl;          // 3
    std::cout << "최소값: " << getMin("apple", "banana") << std::endl; // apple
    return 0;
}

🔹 출력 결과

최소값: 3
최소값: apple

💡 설명

  • int, double 타입은 기본 템플릿을 사용.
  • char* 타입은 특수화된 버전을 사용하여 문자열 비교가 가능하도록 변경됨.

📌 5. 다중 타입 템플릿 (template<typename T1, typename T2>) 활용법

🔹 (1) 두 개 이상의 타입을 사용하는 템플릿

  • 템플릿은 여러 개의 타입 매개변수를 가질 수 있음.
  • template<typename T1, typename T2> 형태로 선언.

💡 예제: 두 개의 다른 타입을 비교하는 템플릿

#include <iostream>

template<typename T1, typename T2>
void printTypes(T1 a, T2 b) {
    std::cout << "첫 번째 값: " << a << ", 두 번째 값: " << b << std::endl;
}

int main() {
    printTypes(10, 3.14);  // int와 double 타입 혼합
    printTypes('A', "Hello");  // char와 string 혼합
    return 0;
}

🔹 출력 결과

첫 번째 값: 10, 두 번째 값: 3.14
첫 번째 값: A, 두 번째 값: Hello

💡 설명

  • printTypes(10, 3.14); → T1 = int, T2 = double으로 추론.
  • printTypes('A', "Hello"); → T1 = char, T2 = const char*으로 추론.

📌 6. 정리

개념  설명
함수 템플릿 기본 개념 template<typename T>을 사용하여 범용적인 함수 작성
템플릿 함수 호출 방식 자동 타입 추론 또는 명시적 타입 지정 가능
템플릿 특수화 특정 타입에 대해 다른 구현을 제공
다중 타입 템플릿 template<typename T1, typename T2>을 사용하여 다양한 타입 지원