템플릿은 STL 제너릭 프로그래밍의 핵심이다.

 

템플릿을 사용하는이유?

: 범용적으로 사용함에 있어, 미리 타입을 정하지 않고,  일반화(generic)된 프로그래밍을 하기위함

 

컴파일러가 함수 호출인자 타입을 보고 템플릿 함수의 매개변수 타입을 결정하여 실제 함수인 템플릿 인스턴스 함수를 만들어 냅니다.

 

 

 

[함수 템플릿]

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
 
#include <iostream>
using namespace std;
 
/**
*    템플릿
*/
 
class Student{
    int kor_score;
    int eng_score;
public:
    Student(int _kor, int _eng ) : kor_score(_kor), eng_score(_eng){}
    void Print(int num){
        cout<<"["<<num<<"]"<<"한국사 점수 : "<<kor_score<<"점"<<endl;
        cout<<"["<<num<<"]"<<"영어 점수 : "<<eng_score<<"점"<<endl;
    }
};
 
 
template <typename T1, typename T2>    //template<class T1, class T2>
void Print(T1 arg1, T2 arg2){
    cout<< arg1 << "," << arg2 <<endl;
}
 
//템플릿특수화
template<>
void Print(int num, Student * st){
//void Print<>(int num, Student * st){
//void Print<int, Student*>(int num, Student* st){
    st->Print(num);
}
 
template <typename T1, int size>
void PrintArray( T1* arr ){
    for(int i = 0; i < size; ++i ){
        cout<<"["<<i<<"]"<<arr[i]<<endl;
    }
}
 
int main()
{
    Print(10, 20);
    Print(0.4, 0.05);
    Print("ABCD", 10);
    cout<<endl;
 
    Print<int,int>(10, 20);                //함수템플릿타입을 명시적호출
    Print<doubledouble>(0.4, 0.05);
    Print<const char*,int>("ABCD", 10);
    cout<<endl;
    //----------------------------------------------------------
 
    Student s1(100, 50);
    Student s2(90, 30);
    Print(0,&s1);    // 특수화 버전 호출
    Print(1,&s2);    // 특수화 버전 호출 Print<Point>(&s2);->명시적호출
    cout<<endl;
    //----------------------------------------------------------
    int arr[5] = { 1, 2, 3, 4, 5 };    
    PrintArray<int, 5>(arr);
    // 여기서 이렇게 템플릿을 명시적으로 호출해야만 한다.
    // 왜냐하면 T1이라는 정보만을 제공하므로 5라는 템플릿 매개변수 인자를
    // 클라이언트 코드만으로 컴파일러가 추론할 수 없기 때문
 
    //-----------------------------------------------------------
 
    system("pause");
    return 0;
}

 

 

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
#include <string>
using namespace std;
 
/**
* 함수객채(printFunctor)를 사용한 For_each
*/
 
template <typename IterT, typename Func>
void For_each(IterT begin,IterT end, Func pf )
{
    while( begin != end )
    {
        pf( *begin++ ); 
    }
}
 
template <typename T>
struct PrintFunctor
{
    string sep; // 출력 구분자 정보 seperator
public:
    explicit PrintFunctor(const string& s=" "):sep(s) { }
    void operator()(T data) const
    {
        cout << data <<sep;
    }
};
 
void main( )
{
    int arr[5] = {10, 20, 30, 40, 50};
    For_each(arr, arr+5, PrintFunctor<int>());  // 명시적 호출을 해줘야 한다.
    cout << endl;                                // 그렇지 않으면 컴파일러가 
                                                // typename T 를알수없다.
 
    string sarr[3] = {"abc","ABCDE","Hello!"};
    For_each(sarr, sarr+3, PrintFunctor<string>("*\n")); // 구분자 *
    cout << endl;
}
 
 

 

 

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
29
30
#include <iostream>
#include <string>
using namespace std;
 
/**
*    반환타입과 매개변수 타입을 인자로 갖는 함수객체
*/
 
template <typename RetType, typename ArgType>
class Functor
{
public :
    RetType operator( ) (ArgType data)
    {
        cout << data << endl;
        return RetType();
    }
};
void main( )
{
    /**
    *    템플릿의 매개변수와 함수 객체를 결합하면 반환타입과
    *    함수매개변수 타입을 클라이언트가 결정하는 아주 유연한
    *    함수객체를 만들수 있습니다.
    */
    Functor< voidint > functor1;
    functor1( 10 );
    Functor< bool, string > functor2;
    functor2( "Hello!" );
}

 

 

[클래스 템플릿]

 

 

실제로 메타 클래스(클래스를 만드는 클래스)이다. 그리고 이것을 메타프로그래밍이라고 한다. 본질적으로 메타프로그래밍은 프로그램 작성시가 아닌 실행 중 코드를 변경하거나 생성함을 말한다.

 

 

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <iostream>
#include <string>
using namespace std;
 
/**
*    클래스 템플릿
*    :클래스를 만들어내는 틀(Meta코드)
*/
 
#include <iostream>
using namespace std;
 
template < typename T1=intint capT = 100 > //디폴트 매개변수
class Array{
    T1 *arr;
    int size;
    int capacity;
 
public:
    explicit Array(int cap = capT) : arr(NULL), size(0), capacity(cap) {
        arr = new T1[capacity];
    }
    ~Array(){
        delete [] arr;
    }
 
    void Add( T1 data ){
        if( size > capacity)
            throw "오바";
 
        arr[size++] = data;    
    }
    void print() const{
        for(int i = 0; i < size; ++i)
            cout<<"["<<i<<"] "<<arr[i]<<endl;
    }
    int Size() const{
        return size;
    }
    T1& operator[](int idx){
        return arr[idx];
    }
    T1 operator[](int idx) const{
        return arr[idx];
    }    
};
 
int main(){
    
    Array<int> arr; // 정수(클라이언트가 T타입 결정) Array객체
    //Array<> arr;    // 디폴트 매개변수값을 갖는 선언
    try{
        arr.Add(10);
        arr.Add(20);
        arr.Add(30);
    }catchchar * pStrException ){ cout<<pStrException<<endl; }    
    arr.print();
 
    Array<string> sarr; // 문자열
    try{
        sarr.Add("abc");
        sarr.Add("ABC");
        sarr.Add("Hello!");
    }catchchar * pStrException ){ cout<<pStrException<<endl; }    
    sarr.print();
 
 
    system("pause");
    return 0;
}

 

 

 

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
#include <string>
using namespace std;
 
/**
*    클래스 템플릿 특수화
*/
template <typename T>
class ObjectInfo
{
    T data;
public:
    ObjectInfo(const T& d):data(d) { }
    void Print( )
    {
        cout <<"타입 : "<< typeid(data).name() << endl;
        cout <<"크기 : "<< sizeof(data) << endl;
        cout <<"값 : "<< data << endl;
        cout <<endl;
    }
};
template <> // T를 string으로 특수화(클래스 템플릿 특수화)
class ObjectInfo<string>
{
    string data;
public:
    ObjectInfo(const string& d):data(d) { }
    void Print( )
    {
        //cout <<"타입 : "<< typeid(data).name() << endl;
        cout <<"타입 : "<< "string" << endl; //타입 정보 수정
        //cout <<"크기 : "<< sizeof(data) << endl;
        cout <<"문자열 길이 : "<< data.size() << endl; //길이 정보 수정
        cout <<"값 : "<< data << endl; 
        cout <<endl;
    }
};
void main( ) 
{
    ObjectInfo<int> d1(10);
    d1.Print( ); // 객체 정보 출력
 
    ObjectInfo<double> d2(5.5);
    d2.Print( ); // 객체 정보 출력
 
    ObjectInfo<string> d3("Hello!");
    d3.Print( ); // 객체 정보 출력
}
 

 

 

 

 

'0x0001 > C, C++' 카테고리의 다른 글

[C++] 콜백함수( CallBack Function )  (0) 2019.02.08
[C++] 정적함수포인터, 멤버함수포인터  (0) 2019.02.08
[C++] 연산자 오버로딩  (0) 2019.02.08
[C++] 가상소멸자  (0) 2019.02.08
[C언어] 10진수를 2진수로  (0) 2019.02.08

+ Recent posts