Programing/C- programing

C++. template 템플릿. 자유로운 자료형 만들기

sosal 2009. 11. 1. 11:58
반응형

/*
 http://sosal.tistory.com/
 * made by so_Sal
 */



시작하자마자 소스를 펼쳤어요.
간단한 소스를 4개 볼것입니다.
이 소스들만 분석하면 템플릿이 어떤건지
정확하게 이해가 될거같네요!! ㅎㅎ

여튼 탬플릿을 사용하는 목적은
자유로운 변수를 만들기 위함입니다.
어떠한 자료형이 들어오던 간에
전부다 알아서 처리해줍니다.

/*
 * template<class a> == template<typename a> 둘은 같은 의미입니다.
 * class :: C++ 스타일, typename a :: C 스타일
 */


#include<iostream>
using namespace std;

template <class a>  //print라는 함수인데 위에 이상한게 있네요.
void print(a data){     //함수 인자는 위에 템플릿 옆 class a. a라는 변수가 들어간다는 말인데.. 흠..
    cout<<"print함수가 받아온 값은 "<<data<<"입니다."<<endl;
}                             //결국 클레스로 정의된 a라는 변수의 형태로 data를 출력합니다.

int main(){


    print<int> (10);  // int형으로 넘겨줌
    print (10);         // 그냥 숫자 대입? 역시 int형
    print ("korea");  // 문자열 대입? 출력이 되네요
    print (3.12312);  //double형인가요? 출력됩니다.
    return 0;
}

template의 신비는 이렇게 시작합니다.
template <class a, class b, ...... > 함수위에 템플릿으로 선언해주고 아래에 함수를 선언합니다.
void func(a data1,a data2, b data3.......> 템플릿으로 정의해준 데이타 (사실 내용이란건 없지만..)를 자료형으로
이용하여 함수안에 인자로 사용하게 됩니다.
이때 들어오는 인자값은 내용이 전혀 없는 class로 정의된 변수입니다.
어떠한 변수가 들어오면 자동으로 그 변수를 인식하게 되어
특정한 자료형에 갇히지 않고, 어떠한 변수든 자유롭게 사용할 수 있는 함수를 만들 수 있게 됩니다.
그럼 좀더 나아간 소스를 봅니다.

=======================================================================================================

#include<iostream>
using namespace std;

template <class a> //자료형은 템플릿으로 a형,b형 총 2개를 만들었네요
void print(a data, a data2){ //위와 동일한 print 함수를 만들었는데, 변수를 2개 만들었습니다.
    cout<<"print함수가 받아온 값은 "<<data<<"입니다."<<endl;
    cout<<"print함수가 받아온 값은 "<<data2<<"입니다."<<endl;
}

int main(){
    print<int> (10,32); //앞의 <int>는 class a라는 변수를 int형이라고 바꾸는 것입니다.
    print (10,52);         //이렇게 수를 넣으면 일반적으로 int로 들어가게 됩니다.
    print (3.12312,3.24132); //첫번째 인자가 double 형이므로, class a는 double 형태로 바뀌게 되고
                                     //두번째 인자 역시 double형으로 받을 수 있는 형태의 자료이기 때문에 가능합니다.
    /* print (152,52.2231); */   // -> int형과 double을 함께쓰면 error
    print<int> (10,3.14);      //이것은 10과 3이 출력됩니다. class a가 int형으로 인식되었기 떄문입니다.
    print<double> (10,3.14); //이것은 10과 3.14로 출력됩니다. class a가 double형으로 인식되었기 때문입니다.
    return 0;
}

위 주석처리된 print(152,52.2231)을 제외한 결과값입니다.



주석처리 된 부분을 error가 났다고 말했는데, 왜 에러인가?를 보면
처음에 들어온 자료형은 int 형이어서 템플릿은 내부적으로 class a를 int로 바꿉니다.
그다음에 들어오는 변수는 보니까 double형이네요?
이렇게 되면 int형으로 받아야할지 double형으로 받아야 할지
시스템이 고민을 하게 됩니다. (첫번째 변수를 class 템플릿 변수로 인식)
이렇게 고민을 하게 되는 상황에서는 에러가 납니다.

만약 첫번째 인자가 int형인 3이었고, 두번째가 문자열 bb 였다면
어떤걸 선택해야할까요?
그래서 이 방법을 해결하기 위해서는
함수를 호출할때 ex)print<double> (52,22.11) 이런식으로
print 함수가 받는 자료형을 임의로 바꿔주던지,
아니면 template를 선언할때 처음부터 자료형을 따로 주는 방법이 있습니다.

template <class a,class b> //자료형은 템플릿으로 a형,b형 2개를 만들었네요
    void print(a data1, b data2){
}
이렇게 되면 a data1과 b data2에 어떠한 다른 값을 넣더라도
서로 다른 변수로 인식하기 때문에
자유로운 변수 사용이 가능하겠죠??

=======================================================================================================

세번째 소스입니다.


#include<iostream>
using namespace std;

template <class a,class b,int c>
void print(a data, b data2){
    cout<<"print함수가 받아온 값은 "<<data<<"입니다."<<endl;
    cout<<"print함수가 받아온 값은 "<<data2<<"입니다."<<endl;
    cout<<"c="<<c<<endl;
}

int main(){
    print<double,int,232> (10, 3.14);
    return 0;
}

c라는 변수는 print 함수의 매개변수로는 는 전해줄 방법이 없었는데,
print 함수에서 인자값으로 c를 넘기는게 아니라
이런 방식으로 넘길 수 있습니다.


=======================================================================================================


그럼 마지막 소스를 보겠습니다.

#include<iostream>
using namespace std;

template<class a,class b,class c>
void func(a data1,b data2,c data3){
    cout<<"data1 ::"<<data1<<endl;
    cout<<"data2 ::"<<data2<<endl;


    cout<<"data3 ::"<<data3<<endl;
}

int main(){
    func (8,3.14,"sosal이었습니다.");
    return 0;
}

마지막 소스는 1,2,3번 소스를 보셨을을 때 충분히 이해가 가능하실거라 생각합니다.
그럼 template으로 계산기 프로그램을 짜보시면 더욱 도움이 될 듯 하네요. ㅎㅎ