[C++] template
Updated:
개요
template <typename T1, typename T2> class Test
- 특수화
template <typename T1, typename T2> class Test<T1 *, T2 *> {
- 부분 특수화
template <typename T2> class Test<int, T2> {
- 함수 템플릿
template <typename T1, typename T2> void func(T1 t1, T2 t2)
- 함수 템플릿 특수화
- 특수화를 지원하지 않고 오버로딩으로 해결
template <> void func(char t1, string t2) {
- 논타입 템플릿 인자
template <typename T1, int add>
- 디폴트 템플릿 인자
template <typename T = int>
template <typename T1, int add = 5>
- 가변인자 템플릿
template <typename Type, typename... Types>
- fold expression
- C++17
- ‘…’ 위치에 따라 ‘()’의 위치를 결정
template <typename... Types> void func7(Types... ts) { cout << (... + ts) << endl; }
- (E op …)
- (E1 op (… op (EN-1 op EN)))
- (… op E)
- (((E1 op E2) op …) op EN)
- (E op … op I)
- (E1 op (… op (EN?1 op (EN op I))))
- (I op … op E)
- ((((I op E1) op E2) op …) op EN)
- 템플릿 메타 프로그래밍(Template Meta Programming)
- 템플릿을 사용하여 컴파일 타임에 생성되는 코드를 이용하는 프로그래밍 기법
- 장점
- 컴파일 타임에 연산을 처리하므로 실행 속도 증가
- 단점
- 구현이 복잡
- 코드 가독성 저하
- 컴파일 타임에 연산을 처리하므로 디버깅 불가
예제
- 코드
#include <functional> #include <iostream> #include <typeinfo> using namespace std; template <typename T1, typename T2> class Test { public: Test() { cout << "main" << endl; } }; template <typename T1, typename T2> class Test<T1*, T2*> { public: Test() { cout << "specialization" << endl; } }; template <typename T2> class Test<int, T2> { public: Test() { cout << "partial specialization 1" << endl; } }; template <> class Test<int, double> { public: Test() { cout << "partial specialization 2" << endl; } }; template <typename T1, typename T2> void func1(T1 t1, T2 t2) { cout << "main : " << typeid(t1).name() << ", " << typeid(t2).name() << endl; } template <typename T1, typename T2> void func1(T1* t1, T2* t2) { cout << "specialization" << endl; } template <typename T2> void func1(int t1, T2 t2) { cout << "partial specialization 1" << endl; } template <> void func1(int t1, double t2) { cout << "partial specialization 2" << endl; } template <int i> void func1() { cout << i << endl; } template <typename T = int> void func2(T t) { cout << typeid(t).name() << endl; } template <typename T, int add> void func3(T t, int i) { t(i + add); } template <typename T, int add = 5> void func4(T t, int i) { t(i + add); } template <typename Type> void func5(Type t) { cout << t << endl; } template <typename Type, typename... Types> void func5(Type t, Types... ts) { cout << t << ", "; func5(ts...); } template <typename... Types> void func6(Types... ts) { cout << sizeof...(ts) << endl; } template <typename Type, typename... Types> void func7(Type t, Types... ts) { cout << (... + ts) << endl; cout << (ts - ...) << endl; cout << (t + ... + ts) << endl; auto f = [](int i) { cout << i << endl; }; (f(ts), ...); } int factorial_recursion(int n) { if (n == 0) { return 1; } return n * factorial_recursion(n - 1); } template <int N> struct Factorial_TMP { enum { value = N * Factorial_TMP<N - 1>::value }; }; template <> struct Factorial_TMP<0> { enum { value = 1 }; }; int main() { Test<char, int>(); Test<int*, char*>(); Test<int, char>(); Test<int, double>(); cout << "------" << endl; func1('c', 1); func1(new int(1), new char('c')); func1(1, 'c'); func1(1, 1.1); func1<5>(); cout << "------" << endl; func2(1); func2<double>(1); cout << "------" << endl; function<void(int)> f = [](int i) { cout << i << endl; }; func3<function<void(int)>, 1>(f, 1); func3<function<void(int)>, 2>(f, 1); func4(f, 1); cout << "------" << endl; func5(1, 'a'); func5("abc", 1.1, "!"); cout << "------" << endl; func6(1); func6(1, 'a'); cout << "------" << endl; func7(1, 2, 3); cout << "------" << endl; cout << factorial_recursion(10) << endl; cout << Factorial_TMP<10>::value << endl; return 0; }
- 실행 결과
main specialization partial specialization 1 partial specialization 2 ------ main : c, i specialization partial specialization 1 partial specialization 2 5 ------ i d ------ 2 3 6 ------ 1, a abc, 1.1, ! ------ 1 2 ------ 5 -1 6 2 3 ------ 3628800 3628800