All is well

[YYBASIC0305/얌얌코딩] C++ Template(템플릿) 본문

C++/YYBASIC

[YYBASIC0305/얌얌코딩] C++ Template(템플릿)

D0YUN 2025. 3. 5. 09:51

템플릿 (template)

: 매개변수의 타입에 따라 함수/클래스를 생성하는 기능입니다.

  • `template`문법을 사용하여 함수에서 자료형을 유동적으로 지정할 수 있으며, 자료형의 이름은 자유롭게 설정할 수 있습니다.
  • 일반적으로 `T`라는 표기를 사용하며, 이는 타입(Type)의 약자로 자료형을 나타냅니다.
  • 함수 또는 클래스를 호출할 때, 호출자가 원하는 자료형을 입력하면 해당 자료형으로 동작하는 코드가 생성됩니다.
  • 실행 시가 아니라 컴파일 시점에 자료형을 결정하므로, 다양한 자료형을 지원하는 유연한 코드 작성이 가능합니다.
  • 템플릿을 활용하면 코드 중복을 줄이고, 재사용성을 높일 수 있습니다.

템플릿의 장점과 단점

// 장점

  • 코드의 재사용성 증가 : 동일한 로직다양한 자료형적용할 수 있습니다.
  • 편리함 : 형 변환 없이 여러 자료형을 처리할 수 있습니다.
  • 유연성 : 개발자가 특정 자료형에 구애받지 않고 로직을 작성할 수 있습니다.

// 단점

  • 컴파일 시간이 증가 : 템플릿을 사용할 경우, 컴파일 시점에 실제 코드가 생성되므로 컴파일 시간이 길어질 수 있습니다.
  • 디버깅이 어렵다 : 템플릿 기반 코드는 일반적인 함수보다 오류 메시지가 복잡할 수 있습니다.
  • 코드 크기 증가 : 자료형 별로 새로운 코드가 생성되므로, 바이너리 크기가 증가할 가능성이 있습니다.

함수 템플릿 (Function Template)

: 함수 템플릿은 함수 호출 시점(컴파일 시점)에 자료형이 결정됩니다.

// 함수 템플릿의 장점

  • 코드 재사용성을 극대화할 수 있습니다.
  • 다양한 자료형을 지원하면서도 동일한 코드 구조 유지가 가능합니다.

// 함수 템플릿의 단점

  • 컴파일 타임 증가 : 컴파일러가 각 자료형에 맞춰 개별 함수를 생성하므로, 코드의 양이 많아질 수 있습니다.
  • 템플릿이 지원되지 않는 환경에서는 사용이 불가능합니다.

// 함수 템플릿을 사용하지 않는 경우

  • 컴파일 타임이 길어지는 경우 : 실행 속도보다 컴파일 속도가 중요한 경우에는 사용을 지양할 수 있습니다.
  • 레거시 코드(옛날 코드 스타일)와의 호환성 문제 : 템플릿에 익숙하지 않은 개발자가 많을 수 있습니다.
  • 가독성이 중요한 프로젝트 : 여러 명이 함께 개발하는 프로젝트에서는 가독성이 중요하므로, 템플릿이 오히려 복잡성을 증가시킬 수도 있습니다.
  • cf) "보기 좋은 코드" = "알아보기 좋은 코드" (여러 명이 함께 개발하기 때문)

템플릿 특수화 (Template Specialization)

  • 특정 자료형에 대해 일반적인 템플릿이 아닌 특정한 동작을 수행하는 코드를 작성할 수 있습니다.
  • 장점 : 특정 자료형에 대한 최적화가 가능합니다.
  • 단점 : 특수화된 자료형마다 별도의 코드가 필요합니다.

클래스 템플릿 (Class Template)

  • 템플릿을 이용하면 다양한 자료형을 저장할 수 있는 클래스를 만들 수 있습니다.
  • 이는 코드의 재사용성을 높이고 유지보수를 용이하게 합니다.
  • 기존에는 자료형마다 클래스를 따로 정의해야 했지만, 클래스 템플릿을 사용하면 단일 코드로 다양한 자료형을 처리할 수 있습니다.
template <typename T>
class Node {
public:
    T data;       // 노드가 저장할 데이터
    Node* next;   // 다음 노드를 가리키는 포인터
};

위 코드처럼 `T`를 사용하면, `int`, `float`, `char` 등 다양한 자료형을 저장할 수 있는 범용적인 클래스를 만들 수 있습니다.


 

최종 코드

// YYBASIC03_05
#include <iostream>
using namespace std;

/* 함수 템플릿
    : 함수를 사용할 때 자료형이 정해짐 (컴파일 시점에 결정)
    * 장점 : 편리함 - 자료형에 관해서 자율성이 높고, 코드의 재사용성이 높아짐
    * 단점 : 컴파일 시 해당 코드들이 생기기 때문에 컴파일 타임이 증가할 수 있음
    
    * 템플릿 함수를 못쓰는 경우
    - 컴파일 타임이 길어지는 경우
    - 옛날 방식 코드 스타일이 존재하는 경우 - 익숙하지 않은 개발자가 많아서 사용 X
      cf) 보기 좋은 코드 : 알아보기 좋은 코드 (∵ 여러 명이 개발하니까)
*/

// 템플릿을 이용한 일반적인 덧셈 함수
template <typename T>
T Add(T a, T b)
{
    return a + b;   // 템플릿으로 인해 다양한 타입에서 사용 가능
}

// 템플릿을 이용한 일반적인 뺄셈 함수
template <typename T>
T Subtract(T a, T b)
{
    return a - b;
}

/* 템플릿 특수화 (Template Specialization)
    : 특정 자료형에 대해 다른 동작을 정의할 수 있음
*/

// 템플릿 특수화 예시 - int 타입에 대한 특수화
// - int 타입에서는 일반 템플릿이 아니라 이 함수가 실행됨
// - 특수화된 함수는 기존 템플릿과 다른 동작을 할 수 있음
// - 여기서는 특수한 출력 메시지를 추가함
template <>
int Subtract(int a, int b)
{
    cout << ">>> Template Specialization <<<" << "\n";
    return a - b;
}

/* 비효율적인 클래스 설계 예제
    * 아래와 같이 각 자료형을 위한 클래스를 따로 정의하면
    코드가 중복되고, 새로운 자료형이 필요할 때마다 추가적인 클래스를 만들어야 해서 비효율적임
*/

// class Node
// {
//     int data;
//     Node* next;
// };
// 
// 
// class NodeChar
// {
//     char data;
//     Node* next;
// };


/* 클래스 템플릿
    *  클래스 템플릿을 사용하여 다양한 자료형을 저장할 수 있도록 함
    * 코드의 재사용성을 높이고 유지보수를 용이하게 함
*/
template <typename T>
class Node
{
public:
    T data;         // 노드가 저장할 데이터 (자료형은 템플릿 타입)
    Node* next;     // 다음 노드를 가리키는 포인터 (같은 템플릿 타입)
};


int main()
{
    // 템플릿 함수의 사용
    cout << "Add<float> : " << Add<float>(3.f, 5.f) << "\n";    // float형 덧셈
    cout << "Add<int> : " << Add<int>(3, 5) << "\n";    // int형 덧셈


    // 템플릿 특수화의 사용
    cout << "\nSubtract<float> : " << Subtract<float>(3.f, 5.f) << "\n";    // 일반 템플릿 사용
    cout << "Subtract<int> : " << Subtract<int>(3, 5) << "\n";  // 특수화된 함수 사용


    // 템플릿 클래스를 이용한 객체 생성 및 데이터 할당
    Node<float> fNode;  // float 타입 노드
    fNode.data = 10.f;
    cout << "\nfNode.data : " << fNode.data << "\n";

    Node<int> iNode;    // int 타입 노드
    iNode.data = 10;
    cout << "iNode.data : " << iNode.data << "\n";

    return 0;
}

 

// 실행 결과

 

 

LV 11 C++ Template(템플릿)