본문 바로가기

고급C,C++

함수 템플릿

함수 템플릿은 임의 데이터형으로 함수를 정의하는 것을 허용한다.


  • 기본적인 함수 템플릿

//funtemp.cpp - 함수 템플릿 사용하기

#include <iostream>

template <typename t>
void Swap(t & a, t & b);

int main()
{
using namespace std;
int i = 10;
int j = 20;
cout<<"i,j = "<<i<<","<<j<<"...\n";
cout<<"컴파일러가 생성한 int형 교환기를 사용하려면 \n";
Swap(i,j); //void Swap(int &, int &)를 생서한다.
cout<<"이제 i,j = "<<i<<","<<j<<"...\n";

return 0;
}

template<typename t>
void Swap(t & a, t & b)
{
t temp;
temp = a;
a = b;
b = temp;
}








  • 템플릿의 오버로딩

//twotemps.cpp -- 함수 템플리의 오버로딩
#include <iostream>


template<class Any> //원본 템플릿
void Swap(Any & a, Any & b);

template<class Any> //추가 템플릿
void Swap(Any * a, Any * b, int n);
int main()
{

return 0;
}

template <class Any>
void Swap(Any & a, Any & b)
{

Any temp;
temp = a;
a = b;
b = temp;
}
template <class Any>
void Swap(Any * a, Any * b, int n)
{
Any temp;
for(int i = 0; i< n; i++)
{
temp = a[i];
a[i] = b[i];
b[i] = temp;
}
}



  • 명시적 특수화
    • 다음과 같은 구조체를 정의한다고 가정하자
      struct job
      {
          char name[40];
          double salary;
          int floor;
      };
      C++에서는 하나의 구조체를 다른 하나의 구조체에 대힙할 수 있기 때문에 Any형이 job 구조체인 경우에도 위의 코드는 잘 동작한다. 그러나 salary와 floor 멤버만 교환하고, name 멤버는 그대로 두고 싶다고 가정해 보자. 이 경우에는 이제 코드가 달라져야 한다. 그러나 Swap()에 넘겨주는 전달인자는 첫 번째 경우와 같아야 한다. 그렇다면 새로운 코드에 템플릿 오버로딩을 사용할 수 없다. 
       그러나 명시적 특수화(explicit specialization)라는 특수화된 함수 정의를 필요한 코드와 함께 제공할 수 있다. 컴파일러가 함수 호출에 정확히 대응하는 특수화된 정의를 발견하면, 템플릿을 찾기 않고 그 정의를 사용한다.
    • job형을 위한 명시적 특수화 원형
      template<>
      void Swap<job>(job &, job &)

// twoswap.cpp -- specialization overrides a template
#include <iostream>
template <class Any>
void Swap(Any &a, Any &b);


struct job
{
char name[40];
double salary;
int floor;
};
// explicit specialization
template <> void Swap<job>(job &j1, job &j2);
void Show(job &j);
int main()
{
using namespace std;
cout.precision(2);
cout.setf(ios::fixed, ios::floatfield);
int i = 10, j = 20;
cout << “i, j = “ << i << “, “ << j << “.\n”;
cout << “Using compiler-generated int swapper:\n”;
Swap(i,j); // generates void Swap(int &, int &)
cout << “Now i, j = “ << i << “, “ << j << “.\n”;
job sue = {“Susan Yaffee”, 73000.60, 7};
job sidney = {“Sidney Taffee”, 78060.72, 9};
cout << “Before job swapping:\n”;
Show(sue);
Show(sidney);
Swap(sue, sidney); // uses void Swap(job &, job &)
cout << “After job swapping:\n”;
Show(sue);
Show(sidney);
return 0;
}
template <class Any>
void Swap(Any &a, Any &b) // general version
{
Any temp;
temp = a;
a = b;
b = temp;
}
// swaps just the salary and floor fields of a job structure
template <> void Swap<job>(job &j1, job &j2) // specialization
{
double t1;
int t2;
t1 = j1.salary;
j1.salary = j2.salary;
j2.salary = t1;
t2 = j1.floor;
j1.floor = j2.floor;
j2.floor = t2;
}
void Show(job &j)
{
using namespace std;
cout << j.name << “: $” << j.salary
<< “ on floor “ << j.floor << endl;
}



  • 구체화와 특수화
    • 컴파일러가 특정 데이터형에 맞는 함수 정의를 생성하기 위해 템플릿을 사용할 때, 그 결과는 템플릿의 구체화(instantiation)라 한다.
      • 암시적 구체화(implicit instantiation) - 소스에서 사용할때 그에 해당하는 형으로 Swap() 함수를 구체화 한다.
      • 명시적 구체화(explicit instantiation) - 사용자가 직접 구체화 하도록 지시할 수 있다.
        • temp void Swap<int>(int &,int &) // 명시적 구체화
        • 몇시적 특수화와 <> 차이다. // template <> void Swap(int &, int &);

template <class Any>
void Swap (Any &, Any &); // template prototype
template <> void Swap<job>(job &, job &); // explicit specialization for job
int main(void)
{
template void Swap<char>(char &, char &); // explicit instantiation for char
short a, b;
...
Swap(a,b); // implicit template instantiation for short
job n, m;
...
Swap(n, m); // use explicit specialization for job
...
char g, h;
Swap(g, h); // use explicit template instantiation for char
...
}