C++ - 템플릿
C++ 템플릿
1. 개요
코드는 같은데 자료형만 다른 것을 컴파일러가 만들어주는 것이다.
딱히, 성능에는 이득이 없고 개발자만 편한 기능이지만 이 기능은 매우 많이 사용되고 있다.
2. 템플릿 함수
템플릿 함수는 함수의 매개 변수 또는 구현에 사용되는 자료형을 결정하여 생성한다.
일반적으로는 {반환형} {함수 이름} ( {매개변수} ) { {함수 내용} }
으로 선언 가능했던 함수 형태지만 함수 정의에서 template
1
2
3
4
5
6
7
8
9
10
11
12
#include<iostream>
#include<typeinfo>
using namespace std;
template <typename T> T addNumber(T a, T b) {
return a+b;
}
template <typename T1, typename T2> T1 diffAddNumber(T1 a,T2 b) {
return a+b;
}
위와 같이 선언된 템플릿 함수는 실제 사용될때 해당 자료형을 선언하여 쓰게된다.
1
2
3
4
5
6
7
8
int main() {
// 명시적으로 자료형 선언
auto test1 = addNumber<int>(5, 4);
// 입력된 값의 자료형으로 template 자료형 결정
auto test2 = addNumber(5, 3);
auto test3 = diffAddNumber(5, 3.2);
}
만약 특정 데이터 타입에 대해서 다른 작업을 해야하는 경우 template <>
을 이용하여 해당 자료형에 대해서 다시 정의해야한다. 이를 템플릿 특수화라고 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
struct customType {
int x;
int y;
int value;
}
template<typename T> void sort(std::vector<T>& vec){
std::sort(begin(vec), end(vec));
}
template<> void sort(std::vector<customType>& vec) {
std::sort(begin(vec), end(vec), [](customType& data1, customType& data2)->bool { return data1.value < data2.value;});
}
3. 템플릿 클래스
말 그대로 클래스를 템플릿으로 선언하는 것으로 각 자료형에 맞춰서 생성된다.
동일하게 typename에는 모든 종류의 자료형이 들어올 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
template <typename T>
class customContainer {
public:
explicit customContainer(int size) { data_ = new T[size]; size_ = size; }
virtual ~customContainer() { delete data; size_ = 0; }
T& operator[](size_type idx) { return data_[idx]; }
const T& operator[](size_type idx) const { return data_[idx]; }
private:
T* data_;
int size_type;
};
템플릿 클래스도 역시 클래스는 클래스이기 때문에 상속이 가능하며, 추가 자료형의 경우 별도로 정의하면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
template <typename T>
class A {
public:
T data;
int data_1;
};
template <typename T, typename U>
class B : public A<T> {
public:
U data_2;
int data_3;
};
매개 변수 팩(parameter pack)
흡사 함수의 가변 매개변수와 같이, template의 자료형을 가변적으로 사용하는 방식이다.
기본적으로 모두 컴파일 타임에 처리되고 인라인 함수화 되기 때문에 성능에 영향은 없다.
일단 c++17 기준으로 사용법이 다르다. 따라서 아래의 코드를 실행시켜보고 사용해야한다.
1
2
3
4
5
6
7
8
9
#include <iostream>
using namespace std;
int main()
{
cout << __cplusplus << endl;
return EXIT_SUCCESS;
}
이 값이 201700 이하라면 아래와 같이 사용할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <functional>
template<typename T>
T mult(T first) {
return first;
}
template<typename T, typename... Args>
T mult(T first, Args... args) {
return first * mult(args...);
}
using namespace std;
int main()
{
cout << mult(1,2,3,4) << endl;
function<int(int)> fn1 = mult<int>;
cout << fn1(1) << endl;
function<int(int, int, int, int)> fn2 = mult<int, int, int, int>;
cout << fn2(1,2,3) << endl;
return 0;
}
201700이상이라면 아래와 같이 사용할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <functional>
template<typename... Args>
auto mult(Args... args)
{
return (args * ...);
}
using namespace std;
int main()
{
cout << mult(1,2,3,4) << endl;
function<int(int)> fn1 = mult<int>;
cout << fn1(1) << endl;
function<int(int, int, int, int)> fn2 = mult<int, int, int, int>;
cout << fn2(1,2,3) << endl;
return 0;
}