template <typename T>
T Add(T a, T b)
{
return a + b;
}
Add<int>(3,10);
//컴파일 시간에 템플릿 함수를 보고 필요한 함수 생성
int Add(int a, int b)
{
return a + b;
}
template <typename T>
T Add(T a, T b)
{
return a + b;
}
template <class T>
T Add(T a, T b)
{
return a + b;
}
Add<int>(3, 10);
Add(3,10)
// 2 인자 모두 int니까 추측이 가능함.
//이렇게 하면 템플릿화 된 인스턴스를 만든다(오브젝트의 인스턴스가 아니다.)
template<typename T>
class MyArray
{
public:
bool Add(T data)
MyArray();
private:
enum { MAX = 3};
T mArray[MAX];
};
template<typename T>
bool MyArray<T>::Add(T data)
{
if(mSize >= MAX)
{
return false;
}
mArray[mSize++] = data;
return true;
}
template<typename T>// 생성자에도 표시 해야 한다.
MyArray<T>::MyArray()// 생성자에도 표시 해야 한다.
: mSize(0)
{
}
MyArray<int> scores;
scores.Add(10);
MyArray<int> scores;
MyArray scores;// Error
// 컴파일러가 알 수 있는 방법이 없다, 추측할 수 있는 인자도 없는데 어떻게....
template<typename T, size_t N>// N 은 size_t 타입만 가능
class FixedVector
{
public:
private:
T mArray[N];
};
// 템플릿으로 배열의 갯수를 정의할 수 있다. 그것도 컴파일 타임에...
// 이렇게 하면 배열의 갯수를 강제 할 수 있다.
FixedVector<int, 16> numbers;
template<typename T, typename U>
void Print(const T& a, const U& b)
{
cout << a << "/" << b << endl;
}
template<typename T, typename U>
class MyPair
{
public:
T mFirst;
U mSecond;
}
template<>
float Power(float value, float exp)
{
return std::powf(value, exp);
}
Power<float,float>(3.14, 3.5); 호출할 때 위 함수를 호출 함
그렇게 자주 사용하지는 않음.
템플릿(C++) vs Generic(C#)
특정한 템플릿 매개변수를 받도록 템플릿 코드를 커스터마이즈할 수 있음
std::vector에 좋은 예가 있음.
template <class T, class Allocator>
class std::vector<T, Allocator>// 모든 형을 받는 제네릭 vector
{
}
// 일반적인 vector를 사용할 때는 이 틀을 사용한다.
template <class Allocator>
class std::vector<bool, Allocator>// bool을 받도록 특수화된 vector
{
}
// bool 타입의 vector를 사용할 때는 이 틀을 사용한다.
// vector<bool> data;
"std::vector<bool> 특수화는 가치가 좀 있음"
template<typename V, typename EXP>
V Power(const V value, EXP exponent)
{
V result = 1;
while(exponent-- > 0)
{
result *= value;
}
return result;
}
float powerResultFloat = Power(10.f, 2.5f)
template<>
float Power(float value, float exp)
{
return std::powf(value, exp);
}
template<typename V, typename EXP>
V Power(const V value, EXP exponent)
{
}
template<>
float Power(float value, float exp)
{
}
template <class T, class Allocator>
class std::vector<T, Allocator>// 모든 형을 받는 제네릭 vector
template <class Allocator>
class std::vector<bool, Allocator>
template<class T>
class MyArray
{
public:
bool Add(T data);
MyArray();
private:
enum {MAX = 3};
int mSize;
T mArray[MAX];
}
template<>
class MyArray<bool>
{
public:
bool Add(bool data);
MyArray();
private:
enum {MAX = 3};
int mSize;
int mArray;
}
MyArray<bool>::MyArray()
: mSize(0)
, mArray(0)
{
}
bool MyArray<bool>::Add(bool data)
{
if(mSize >= MAX)
{
return false;
}
if(data)
{
mArray |= (1 << mSize++);
}
else
{
mArray &= ~(1 << mSize++);
}
}
프로그래밍은 아니고 방법론
실행중에 수행되어야 할 일을 템플릿으로 작성하여 함수 호출을 없애고 함수가 반환해야할 결과 값을 컴파일 중에 얻어옴
EX)
template<typename T>
class MyArray
{
public:
MyArray();
/*
const T& 로 받는 이유는 T가 개체일 수 있어서,
T가 만약 10m 넘는 개체라면 이를 복사하기란 무리이다.
물론 배열에 저장 할 때는 복사해서 저장할 것이지만
적어도 함수의 매개 변수로 받을 때는 복사를 막기 위해서 const T& 받음
*/
bool Add(const T& data);
size_t GetSize() const;
private:
enum { MAX = 3 };// 괜찮은 트릭
size_t mSize;
T mArray[MAX];
};
template<typename T>
MyArray<T>::MyArray()
: mSize(0)
{
}
template<typename T>
size_t MyArray<T>::GetSize() const
{
return mSize;
}
template<typename T>
bool MyArray<T>::Add(const T& data)
{
if (mSize >= MAX)
{
return false;
}
mArray[mSize++] = data;
return true;
}
template<typename T, size_t N>
class FixedVector
{
public:
FixedVector();
bool Add(const T& data);
size_t GetSize() const;
size_t GetCapacity() const;
private:
size_t mSize;
T mArray[N];// enum 트릭이 없다.
};
template<typename T, size_t N>
FixedVector<T, N>::FixedVector()
: mSize(0)
{
}
template<typename T, size_t N>
size_t FixedVector<T, N>::GetSize() const
{
return mSize;
}
template<typename T, size_t N>
size_t FixedVector<T, N>::GetCapacity() const
{
return N;
}
template<typename T, size_t N>
bool FixedVector<T, N>::Add(const T& data)
{
if (mSize >= N)
{
// 여기에 assert를 넣어서 사용자가 capacity를 너무 적게 넣었다는 것을
// 빨리 알릴 수 있다.(현명한 Exception 처리)
return false;
}
mArray[mSize++] = data;
return true;
}
template <typename T>
static T Divide(T value1, T value2)
{
return value1 / value2;// value2가 0인것 어떻게 확인???
}
template<>
class MyArray<bool>
{
public:
bool Add(bool data);
MyArray();
private:
enum {MAX = 3};
int mSize;
int mArray;
}
MyArray<bool>::MyArray()
: mSize(0)
, mArray(0)
{
}
bool MyArray<bool>::Add(bool data)
{
if(mSize >= MAX)
{
return false;
}
if(data)
{
mArray |= (1 << mSize++);
}
else
{
mArray &= ~(1 << mSize++);
}
}