Template 템플릿

MwG·2025년 1월 1일

C++

목록 보기
6/14

Template

사용자가 원하는 타입을 넣어주면 그에 맞게 짜여지는 틀과 같은 역할을 한다.

template <typename T>
void print(T w)
{
	cout << w << endl;
}

int main()
{
	string s;
    cin >> s;
    
    print(s);
    
    int a;
    cin >> a;
    
    print(a);
}
template <typename T>
class Print
{

public:
  
    Print()
    {
    }

    void pt()
    {
        std::cout << typeid(T).name() << std::endl;
    }



};

int main()
{

    Print<std::string> print_s;
    print_s.pt();
    Print<int> print_i;
    print_i.pt();


	return 0;
}

위 코드처럼 들어가는 변수의 타입에 맞게 코드가 실행된다.

위 경우들 처럼 클래스 템플릿에 인자를 전달해서 실제 코드를 생성하는 것을 클래스 템플릿 인스턴스화 (class template instantiation)라고 한다.

템플릿 특수화(template specializtion)

템플릿을 할 때 일부 경우에 대해선 따로 처리해주는 것이다.

template <typename T, typename A>
class Print
{

public:
  
    Print()
    {
    }

    void pt()
    {
        std::cout << typeid(T).name() << std::endl;
    }



};

template <>
class Print<int, float>
{

public:

    Print()
    {
        std::cout << "float or int~~" << std::endl;
    }


};

template <typename B>
class Print<std::string,B>
{

public:

    Print()
    {
        std::cout << "string~~" << std::endl;
    }


};

int main()
{

    Print<std::string, double> print_s;
    Print<int, float> print_i;


	return 0;
}

이런식으로 원래 선언한 템플릿의 개수에 맞추어 자신이 따로 처리하고 싶은 경우에 대하여 템플릿 특수화를 진행할 수 있다.

함수 객체(Function object / Functor)

template<typename T, typename Comp>
void bubble_sort(T& cont, Comp& comp)
{
    for (int i = 0; i < cont.size(); i++) 
    {
        for (int j = i + 1; j < cont.size(); j++)
        {
            if (!comp(cont[i], cont[j])) 
            {
                int temp = cont[i];
                cont[i] = cont[j];
                cont[j] = temp;
            }
        }
    }
}

bool comp1(int a, int b)
{
    return (a > b);
}

bool comp2(int a, int b)
{
    return (a < b);
}


int main()
{
    std::vector<int> v;

    v.push_back(1);
    v.push_back(4);
    v.push_back(2);
    v.push_back(6);
    v.push_back(3);

    bubble_sort(v, comp1);

    for (int i = 0; i < v.size(); i++)
    {
        std::cout << v[i] << std::endl;
    }

코드를 입력하세요

    bubble_sort(v, comp2);
   
    for (int i = 0; i < v.size(); i++)
    {
        std::cout << v[i] << std::endl;
    }

	return 0;
}

함수 객체가 없었다면 오름차순, 내림차순 정렬에 대하여 만들어줘야 하지만(함수포인터를 쓸 필요없이) 사용자가 원하는 조건에 대한 클래스를 만들어 주어서 실행할 수 있다는 점에서 더 간편하고 효율적이다.

타입이 아닌 템플릿 인자 (non-type template arguments)

template<typename T, int num>
void print(T s)
{
	std::cout << s << " " << num << std::endl;
}

int main()
{
	std::string s;
	std::cin >> s;

	print<std::string, 5>(s);

	return 0;
}

이와 같이 템플릿에 전달하는 인자가 타입이 아닌 정수와 같은 변수도 가능하다. 정수 이외에도(c++ 20부터) 밑에 있는 여러 자료형들도 사용이 가능해졌다. ->컴파일 타임에 값들이 정해져야 하는 것에 많이 사용
ex)STL의 array 경우 std::array<int, 2> arr 이런 식으로 미리 크기를 알려줄 수 있다.

  1. 정수 타입들 (bool, char, int, long 등등). 당연히 float 과 double 은 제외

  2. 포인터 타입

  3. enum 타입

  4. std::nullptr_t (널 포인터)

만약 아무 값도 전달해주지 않으면 컴파일 오류가 생긴다.

이를 방지하기 위해

디폴트 템플릿 인자

미리 디폴트 값을 정해두어 아무 값도 전달하지 않아도 실행될 수 있게 할 수 있다.

template<typename T, int num = 5>
void print(T s)
{
	std::cout << s << " " << num << std::endl;
}

int main()
{
	std::string s;
	std::cin >> s;

	print<std::string>(s);

	return 0;
}

타입 또한 디폴트로 전달이 가능하다.
최소값을 구하는 함수를 만들 때

template<typename T>
struct Compare
{
	bool operator()(const T& a, const  T& b) const { return a < b; }
};

template<typename T, typename Comp = Compare<T>>//디폴트로 설정해준 타입에 따라서 클래스가 실행됨
T Min(T a, T b) {
	Comp comp;
	if (comp(a, b)) {
		return a;
	}
	return b;
}



int main()
{
	int a = 3, b = 5;
	std::cout << "Min " << a << " , " << b << " :: " << Min(a, b) << std::endl;

	std::string s1 = "abc", s2 = "def";
	std::cout << "Min " << s1 << " , " << s2 << " :: " << Min(s1, s2)
		<< std::endl;

	return 0;
}

<출처>

모두의 코드 c++

0개의 댓글