템플릿은 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<double, double>(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< void, int > 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=int, int 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); }catch( char * pStrException ){ cout<<pStrException<<endl; } arr.print(); Array<string> sarr; // 문자열 try{ sarr.Add("abc"); sarr.Add("ABC"); sarr.Add("Hello!"); }catch( char * 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 |