템플릿의 다중 매개변수

  • 서로 다른 이름을 사용하여 다중 매개변수를 정의 가능
  • 매개변수가 다르다면 서로 타입이 다를 수 있음
template <typename T1,typename T2>

void func(T1 a, T2 b)
{
		std::cout << " " << std::endl;
}

func<int,doulbe>(10,20.05); //T1은 int T2는 double인 함수 생성됨

func('A',12.4);//타입을 명시하지는 않았지만 컴파일러가 맞춰서 해줌

실제 적용 코드

#include <iostream>

template <typename T1,typename T2>//이후에 나오는 T라는 문자는 typename이다.
T1 max(T1 a, T2 b)
{
	return (a > b) ? a : b;
}

int main()
{
	int a = 10;
	int b = 20;

	double c = 1.234;
	double d = 3.456;
	std::cout << max<int,double>(a, c) << std::endl;
}

 

템플릿의 특수화

  • 특정 자료형에 대해서는 템플릿을 사용하지 않고 별도 구현한 함수를 사용하도록 구현 가능
template <typename T>
T min(T a , T b)
{
		return (a<b>?a:b;
}

template<>//std::string type의 인자에 대해서 사용하는 명시적 특수화
std::string min(std::string a, std::string b)
{
		return (a.length() < b.length()) ? a:b;
}

class 템플릿

  • 함수 템플릿과 유사한, 클래스에 대한 템플릿 구현 지원
  • 클래스의 “설계도”
  • 컴파일러가 타입에 따라 적절한 클래스를 생성해 줌

예제 코드

#include <iostream>
#include <string>

class Item
{
private:
	std::string name;
	int value;
public:
	Item(std::string name,int value)
		:name{name},value{value}{}
	std::string getName() const
	{
		return name;
	}
	int getValue() const
	{
		return value;
	}

};
  • 위의 코드를 템플릿 화 시켜보겠다.
#include <iostream>
#include <string>

template <typename T>
class Item
{
private:
	std::string name;
	T value;
public:
	Item(std::string name,T value)
		:name{name},value{value}{}
	std::string getName() const
	{
		return name;
	}
	T getValue() const
	{
		return value;
	}

};

int main()
{
	Item<int> i{ "A",10 };//클래스 생성 됨
	std::cout << i.getName() << std::endl;
	std::cout << i.getValue() << std::endl;

	Item<double> d{ "B",1.345 };//클래스 생성 됨
	std::cout << i.getName() << std::endl;
	std::cout << i.getValue() << std::endl;
}

형식 자체는 우리가 위에서 배운 템플릿과 유사하다. 우리가 템플릿 형식으로 클래스를 정의해 놓고 해당 클래스를 선언하면 객체 생성시 ‘<>’안의 type을 보고 컴파일러가 클래스를 생성하는 구조다.

💡

여기서 조심! ‘같은 이름의 Item클래스가 두개가 생기는데 가능한가요?’라는 의문을 갖을 수 있는데 템플릿 클래스의 사용에서는 “Item”까지가 클래스 이름이라 Item와 Item은 전혀 다른 클래스이다.

다중 매개변수 템플릿 클래스

  • 방식은 비슷하다.
#include <iostream>
#include <string>

template <typename T1,typename T2>
class Item
{
private:
	T1 name;
	T2 value;
public:
	Item(T1 name,T2 value)
		:name{name},value{value}{}
	T1 getName() const
	{
		return name;
	}
	T2 getValue() const
	{
		return value;
	}

};

int main()
{
	Item<std::string,int> i{ "A",10 };//클래스 생성 됨
	std::cout << i.getName() << std::endl;
	std::cout << i.getValue() << std::endl;

	Item<std::string,double> d{ "B",1.345 };//클래스 생성 됨
	std::cout << d.getName() << std::endl;
	std::cout << d.getValue() << std::endl;
}

클래스 템플릿의 (부분) 특수화

💡

만약 내가 두 번째로 오는 인자가 double일 때만 다르게 하고 싶다면

#include <iostream>
#include <string>

template <typename T1,typename T2>
class Item
{
private:
	T1 name;
	T2 value;
public:
	Item(T1 name,T2 value)
		:name{name},value{value}{}
	T1 getName() const
	{
		return name;
	}
	T2 getValue() const
	{
		return value;
	}

};

template <typename T1>
class Item<T1,double>// 두 개의 인자를 넣으라고 명시해 주는 것
{
private:
	T1 name;
	double value;
public:
	Item(T1 name, double value)
		:name{ name }, value{ value } {}
	T1 getName() const
	{
		return name;
	}
	double getValue() const//값을 2배로 하고싶다.
	{
		return 2*value;
	}

};

template <typename T1>
class
{
private:
	T1 name;
	double value;
public:
	Item(T1 name, double value)
		:name{ name }, value{ value } {}
	T1 getName() const
	{
		return name;
	}
	double getValue() const//값을 2배로 하고싶다.
	{
		return 3*value;
	}

};

int main()
{
	Item<std::string,int> i{ "A",10 };//클래스 생성 됨
	std::cout << i.getName() << std::endl;
	std::cout << i.getValue() << std::endl;

	Item<std::string,double> d{ "B",1.345 };//클래스 생성 됨
	std::cout << d.getName() << std::endl;
	std::cout << d.getValue() << std::endl;
}

여기서 우리가 생소한 것이 하나 있다

template <typename T1>
class Item<T1,double>// 두 개의 인자를 넣으라고 명시해 주는 것
  • 해당 특수화 템플릿에서는 컴파일러에게 알려줄 typename은 T1 하나지만 해당 템플릿을 사용할 때 인자를 두 개 받아 한다고 명시해 주는 것이다.
  • why?
    int main()
    {
    		Item<int> a{2,3.4};
    		
    		Item<int, double> b{5,5.6};
    }

    컴파일러는 명시해 주지 않을 시 어떠한 템플릿인지 정확하게 알 지 못한다.

profile
개발로그

0개의 댓글