개발자 면접 공부/C-C++

템플릿(Template)

chogyujin 2024. 7. 1. 13:21
728x90

1. 개요

오늘은 C++에 템플릿(template)에 대해 알아보도록 하겠습니다.


2. 설명

템플릿은 어린시절에 한번쯤 사용했을 모양자와 같습니다.
모양자에는 다양한 종류의 도형들이 틀로 만들어져 있습니다. 이 틀을 활용하면 누구나 정말 반듯한 네모를 그릴수도 있고 별도 그릴수 있습니다.
템플릿의 생산성이 뛰어난 이유도 이와 같습니다. 정말 완성도 높은 코드를 모양자로 찍어내듯 생성할 수 있기 때문입니다.
특히 소스코드의 완성도를 높인 상태에서 STL처럼 확실하게 검증된 라이브러리를 사용한다면 완성도와 생산성, 두마리 토끼를 한꺼번에 잡을 수 있습니다.
템플릿을 많이쓰면 컴파일 속도가 느려지지만 최신 C++ 개발 트렌드를 따르려면 템플릿은 선택이 아니라 필수입니다. 생산성이 높고 유지보수성이 뛰어난 코드가 당연히 좋은 코드이기 때문입니다.

 


3. 함수형 템플릿

그럼 템플릿을 왜 사용할까요??

아래의 코드를 보시죠

int add(int x, int y) 
{
    return x + y;
}

double add(double x, double y) 
{
    return x + y;
}

이 코드를 보면 오버로딩을 통해 add함수 두개를 선언하였습니다.

하지만 이렇게 많이 선언을 하다 보면 이러한 함수가 나올수가 있습니다.

int add(int x, int y) 
{
    return x + y;
}

double add(double x, double y) 
{
    return x + y;
}
std::string add(std::string x, std::string y)
{
	return x+y;
}

이렇게 사용을 하게 된다면 아래로 쭉 함수가 이어지게 될것입니다.
이것은 소스코드가 길어지게 될것이며, 가독성이 매우 떨어질겁니다.

하지만 템플릿을 사용하면 이렇게 줄일수있습니다.

template<typename T>
T add(T x, T y)
{
    return x + y;
}

소스코드로 하나로 만들어버릴수 있습니다.

이 경우는 함수를 호출하는 부분에서 만약 T라는 인자를 암시적으로 타입을 추론하여 컴파일타임에 만들어줍니다.

하지만 만약 x는 int y는 float을 원하면 이렇게 해야합니다.

template<typename T, typename U>
T add(T x, U y)
{
    return x + y;
}

이러면 T는 int Type으로 추론 되며 U는 float으로 추론이 됩니다. 하지만 return은 T로 return 하기 때문에 int형으로 추론이 됩니다.

자 그러면 템플릿이 어떻게 저렇게 추론하고 함수를 부를수있는지 궁금할겁니다.

함수 템플릿은 자동으로 호출이 되면 컴파일때 그것에 맞는 함수를 만들어줍니다.
하지만 중복이 될 경우 링커에서 중복 제거를 해줍니다.

그렇지만 요즘의 컴파일러는 매우 뛰어난 성능을 가지고있기 때문에 컴파일 타임에 이것이 중복함수인것을 확인하고 제거를 해줍니다.

하지만 다른 타입이 들어올경우 알아서 함수를 생성하고 템플릿 인스턴스 테이블이라는 곳에 포인터로 지목당해 관리되고있습니다.


4. 클래스 템플릿

클래스 템플릿은 다음과 같이 사용할수 있습니다.

#include <iostream>
using namespace std;
template <class T>
//template <typename T> //혹은 이렇게
class Calcu
{
private:
    T num1;
    T num2;
public:
    Calcu(T num1, T num2) 
    {
        this->num1 = num1;
        this->num2 = num2;
    }
    T GetAdd()
    {
        return num1 + num2;
    }
};
int main()
{
    Calcu<int> calcu1(10, 20);
    cout << calcu1.GetAdd() << endl;
    
    Calcu<double> calcu2(10.52, 20.24);
    cout << calcu2.GetAdd() << endl;
}

함수 템플릿과 다르게 암시적으로 타입추론을 하는것이 아닌 <> 을 통해 명시적으로 지정을 해줘야 합니다.
이 코드의 결과값은 다음과 같습니다.

여기에 있는 클래스 템플릿도 함수형 템플릿과 마찬가지로 만약 int로 타입지정을 해주면 int로 고정이 됩니다.


5. 템플릿 특수화

템플릿에는 템플릿 특수화라는 기능이 존재합니다.

템플릿에서 미리 지정해놓은 타입이 들어왔을 경우 따로 처리하고 싶을때 사용합니다.

#include <iostream>
using namespace std;
template <class T>
//template <typename T> //혹은 이렇게
class Calcu
{
private:
    T num1;
    T num2;
public:
    Calcu(T num1, T num2) 
    {
        cout << "일반 템플릿" << endl;
        this->num1 = num1;
        this->num2 = num2;
    }
    T GetAdd()
    {
        return num1 + num2;
    }
};

template<>
class Calcu<int>
{
    int num1;
    int num2;
public:
    Calcu(int num1, int num2) 
    {
        cout << "템플릿 특수화" << endl;
        this->num1 = num1;
        this->num2 = num2;
    }
    int GetAdd() 
    {
        return num1 + num2;
    }
};

int main()
{
    Calcu<int> calcu1(10, 20);
    cout << calcu1.GetAdd() << endl;

    Calcu<double> calcu2(10.52, 20.24);
    cout << calcu2.GetAdd() << endl;
}

이렇게 클래스 같은 이름이여도 미리 지정된 int로 지정을 하게된다면 다음과 같은 값이 나옵니다.

하나는 특수화된 템플릿, 하나는 일반으로 넘어가게 됩니다.

약간 클래스 오버로딩 같은 느낌이 나네요ㅎ

함수도 템플릿 특수화가 가능합니다.

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
template <typename T>
T add(T x, T y) 
{
    cout << "일반 템플릿" << endl;
    return x + y;
}

template<>
char* add(char* s1, char* s2)
{
    cout << "템플릿 특수화" << endl;
    char* str = new char[100];
    strcpy(str, s1);
    strcat(str, s2);
    return str;
}

int main()
{
    char num1[] = "10", num2[] = "20";
    cout << add(num1, num2) << endl;
    int num3 = 10, num4 = 20;
    cout << add(num3, num4) << endl;
    return 0;
}


6. Ref

https://coding-factory.tistory.com/696

 

[C++] 템플릿(template) 사용법 & 예제 총정리

템플릿이란? 템플릿은 어린시절에 한번쯤 사용했을 모양자와 같습니다. 모양자에는 다양한 종류의 도형들이 틀로 만들어져 있습니다. 이 틀을 활용하면 누구나 정말 반듯한 네모를 그릴수도 있

coding-factory.tistory.com

 

'개발자 면접 공부 > C-C++' 카테고리의 다른 글

정적 링킹 vs 동적 링킹  (0) 2024.07.04
C++ 11 범위기반 for문 (for each)  (0) 2024.06.16
extern 쓰는법  (0) 2024.06.11
Volatile  (0) 2024.04.29
네임 맹글링  (0) 2024.04.14