3 분 소요

개요

  • 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