Template

정혜창·2024년 12월 30일

독학

목록 보기
17/28
post-thumbnail

OOP 실습을 해보면서 템플릿에 대해 공부는 했지만 여전히 개념이 약간 부실한 상태라 한번 정립하고자 한다.

템플릿(Template)은 C++에서 제네릭 프로그래밍을 구현할 수 있게 해주는 매우 중요한 기능이다. 이를 통해 타입에 상관없이 다양한 데이터 타입을 처리할 수 있는 코드를 작성할 수 있다. 템플릿은 클래스 템플릿과 함수 템플릿으로 나누어 진다.

1. 함수 템플릿 (Function Template)

함수 템플릿은 함수의 매개변수 타입을 일반화하여 특정 타입에 관계없이 함수를 재사용할 수 있게 한다.

예시

#include <iostream>
using namespace std;

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

int main() {
    cout << add(10, 20) << endl;        // 30, int 타입	
    cout << add(3.5, 4.5) << endl;      // 8, double 타입
    cout << add('A', 'B') << endl;      // 159, char 타입
    return 0;
}
  • template <typename T>는 함수의 매개변수 타입템플릿 매개변수 T로 지정한다. 이때 T는 함수가 호출될 때 자동으로 추론된다.
  • add(10, 20)와 같이 호출하면 Tint로 추론되고, add(3.5, 4.5)와 같이 호출하면 Tdouble로 추론된다.
  • 이렇게 함수 템플릿을 사용하면 매번 타입을 지정하지 않고 다양한 타입에 대해 동일한 기능을 수행할 수 있다.

2. 클래스 템플릿 (Class Template)

클래스 템플릿은 클래스의 데이터 타입을 템플릿 매개변수로 받아서, 다양한 데이터 타입에 대해 동일한 클래스 구현을 할 수 있게 한다.

예시

#include <iostream>
using namespace std;

// 클래스 템플릿 정의
template <typename T>
class Box {
private:
    T value;  // 템플릿 타입 T를 사용하는 멤버 변수

public:
    Box(T val) : value(val) {} // 매개변수 생성자

    T getValue() {			
        return value;
    }

    void setValue(T val) {
        value = val;
    }
};

int main() {
    Box<int> intBox(10);          // int 타입에 대한 Box
    Box<double> doubleBox(3.14);  // double 타입에 대한 Box

    cout << "intBox: " << intBox.getValue() << endl;
    cout << "doubleBox: " << doubleBox.getValue() << endl;

    intBox.setValue(20);
    doubleBox.setValue(6.28);

    cout << "intBox after set: " << intBox.getValue() << endl;
    cout << "doubleBox after set: " << doubleBox.getValue() << endl;

    return 0;
}
  • template <typename T>Box 클래스가 어떤 타입에도 대응할 수 있게 해주는 템플릿 선언이다.

  • Box<int> intBox(10);Box 클래스를 int 타입으로 인스턴스화한 예시이다.

    • 이것에 대해 보충설명을 살짝하자면 사실 꺽쇠는 vector을 보면서 정말 많이 봤다. 이제야 깨달은 거지만 vector는 템플릿 클래스로 구현되어 있는 것이다. (컨테이너이면서 클래스임) 그리고 표준 템플릿 라이브러리 STL의 대부분은 템플릿 클래스로 이루어져 있다. (예외도 있다. std::string)
    • 그러니깐 평소 우리가 보던 vector<int> intBox; 같은경우는 '백터의 클래스에서 intBox 라는 객체를 생성한다. 이때 인스턴스 타입은 int' 라는 말이다.
  • 마찬가지로 Box<double> doubleBox(3.14);Box클래스를 double타입으로 인스턴스화한 예시이다.


3. 템플릿 특수화

템플릿을 사용할 때, 특정 타입에 대해서만 다르게 동작하도록 하고 싶을때도 있을 것이다. 이럴때 템플릿 특수화를 한다. 이를 통해 템플릿이 특정 타입에 대해 다른 구현을 사용하도록 할 수 있다.

예시

#include <iostream>
using namespace std;

// 기본 템플릿
template <typename T>
class Printer {
public:
    void print(T value) {
        cout << value << endl;
    }
};

// 템플릿 특수화 (int 타입에 대해서만 다르게 처리)
template <>
class Printer<int> {
public:
    void print(int value) {
        cout << "Integer value: " << value << endl;
    }
};

int main() {
    Printer<string> stringPrinter;
    stringPrinter.print("Hello, Templates!");

    Printer<int> intPrinter;
    intPrinter.print(42);  // 특수화된 print 함수 호출

    return 0;
}
  • 기본 템플릿은 print메소드(멤버함수)를 모든 타입에 대해 동일하게 처리한다.
  • 그러나 Printer<int> 에 대해 템플릿을 특수화하여 int타입에 대해서는 다른 방식으로 출력하도록 했다.
  • 따라서 Printer<int>가 호출될 때 특수화된 print 함수가 실행된다.

4. 템플릿과 여러타입

템플릿은 하나 이상의 매개변수를 가질 수도 있다. 이를 통해 여러 데이터 타입을 동시에 다룰 수 있다.

예시

#include <iostream>
using namespace std;

// 두 개의 타입을 받는 템플릿
template <typename T, typename U> 
T add(T a, U b) {
    return a + b;
}

int main() {
    cout << add(10, 20.5) << endl;   // int + double => 결과는 double
    cout << add(5.5, 2) << endl;     // double + int => 결과는 double

    return 0;
}
  • 여기서 add 함수는 두 개의 타입TU를 매개변수로 받는다. 여기서 매개변수 타입이 서로 다를 때도 동작한다.

템플릿 사용의 장점

  • 재사용성 : 다양한 타입에 대해 동일한 코드를 사용할 수 있다.
  • 유연성 : 템플릿을 통해 코드가 다양한 타입에 대해 동작하도록 할 수 있다.
  • 타입 안정성 : 컴파일 타임에 타입체크가 이루어진다. 따라서 런타임 오류를 줄일 수 있다.
profile
Unreal 1기

0개의 댓글