[따배C++] 13. 템플릿
Created: June 6, 2021 11:26 AM
Tag: specialization, template, templatize
13.1 템플릿
템플릿을 통해 반복되는 코드의 작성을 피할 수 있다. 다음은 자료형 외에 동일한 코드를 반복해서 사용하고자 하는 경우에 대해 예시이다.
#include <iostream>
template<typename T> // 변수명을 짓듯
T getMax(T x, T y)
{
return ((x > y) ? x : y);
}
int main(void)
{
std::cout << getMax(1, 2) << std::endl;
std::cout << getMax(3.14, 1.592) << std::endl;
std::cout << getMax(1.0f, 3.4f) << std::endl;
std::cout << getMax('a', 'c') << std::endl;
return (0);
}
// result
// 2
// 3.14
// 3.4
// c
13.2 클래스 템플릿 templatize
// main.cpp
#include "MyArray.h"
int main(void)
{
MyArray<double> my_array(10);
for (int i = 0; i < my_array.getLength(); ++i)
my_array[i] = i * 0.5;
my_array.print();
return (0);
}
// ==============================
// MyArray.h
#include <assert.h> // for assert()
#include <iostream>
template<typename T>
class MyArray
{
private:
int m_length;
T *m_data; // <-
public:
MyArray()
{
m_length = 0;
m_data = nullptr;
}
MyArray(int length)
{
m_data = new T [length];
m_length = length;
}
~MyArray()
{
reset();
}
void reset()
{
delete[] m_data;
m_data = nullptr;
m_length = 0;
}
T &operator[](int index)
{
assert(index >= 0 && index < m_length);
return (m_data[index]);
}
int getLength()
{
return (m_length);
}
void print()
{
for (int i = 0; i < m_length; ++i)
std::cout << m_data[i] << " ";
std::cout << std::endl;
}
};
13.3 자료형이 아닌 템플릿 매개변수 non type parameters
// main.cpp
#include "MyArray.h"
int main(void)
{
MyArray<double> my_array(10);
for (int i = 0; i < my_array.getLength(); ++i)
my_array[i] = i * 0.5;
my_array.print();
return (0);
}
// ==============================
// MyArray.h
#include <assert.h> // for assert()
#include <iostream>
template<typename T>
class MyArray
{
private:
int m_length;
T *m_data; // <-
public:
MyArray()
{
m_length = 0;
m_data = nullptr;
}
MyArray(int length)
{
m_data = new T [length];
m_length = length;
}
~MyArray()
{
reset();
}
void reset()
{
delete[] m_data;
m_data = nullptr;
m_length = 0;
}
T &operator[](int index)
{
assert(index >= 0 && index < m_length);
return (m_data[index]);
}
int getLength()
{
return (m_length);
}
void print()
{
for (int i = 0; i < m_length; ++i)
std::cout << m_data[i] << " ";
std::cout << std::endl;
}
};
자료형이 아닌 객체에 대한 템플릿화에 대해 알아보자. 한편 템플릿 기능은 코드에 따라 컴파일을 다르게 해주는 개념으로 이에따라 일부 객체들은 반드시 컴파일 전에 값이 결정되어 있어야 한다.
// main.cpp
#include "MyArray.h"
int main(void)
{
MyArray<double, 100> my_array;
for (int i = 0; i < my_array.getLength(); ++i)
my_array[i] = i + 65;
my_array.print();
return (0);
}
// ==============================
// MyArray.h
#include <assert.h>
#include <iostream>
template<typename T, unsigned int T_SIZE>
class MyArray
{
private:
T *m_data; // T m_data[T_SIZE]
public:
MyArray()
{
m_data = new T [T_SIZE];
}
// ...
int getLength()
{
return (T_SIZE);
}
void print()
{
for (int i = 0; i < T_SIZE; ++i)
std::cout << m_data[i] << " ";
std::cout << std::endl;
}
};
13.4 함수 템플릿 특수화 specialization
특정 타입에 대해 함수를 특수화 하고자 한다면 다음의 함수 템플릿 특수화를 활용할 수 있다.
#include <iostream>
using namespace std;
template<typename T>
T getMax(T x, T y)
{
return ((x > y) ? x : y);
}
template<>
// char type에 대해 instanciation이 되는 경우에는 다음의 코드를 사용!
char getMax(char x, char y)
{
cout << "Warning : Comparing chars" << endl;
return ((x > y) ? x : y);
}
int main(void)
{
cout << getMax(1, 2) << endl;
cout << getMax<double>(1, 2) << endl; // 강제로 double로 빌드
cout << getMax('a', 'b') << endl; // Warning
return (0);
}
13.5 클래스 템플릿 특수화 specialization
#include <iostream>
#include <array>
using namespace std;
template<typename T>
class A
{
public:
A(const T& input)
{}
void doSomething()
{
cout << typeid(T).name() << endl;
}
void test()
{}
};
template<>
class A<char>
{
public:
A(const char & temp);
void doSomething()
{
cout << "Char type specialization" << endl;
}
};
int main(void)
{
A<int> a_int(1);
A<double> a_double(3.14);
A<char> a_char('a');
a_int.doSomething();
a_double.doSomething();
a_char.doSomething();
}
13.6 템플릿을 부분적으로 특수화하기 partial specialization
#include <iostream>
#include <string.h>
using namespace std;
template <class T, int size>
class StaticArray
{
private:
T m_array[size];
public:
T * getArray() { return (m_array); }
T &operator[](int index)
{
return (m_array[index]);
}
};
template <typename T, int size>
void print(StaticArray<T, size> &array)
{
for (int count = 0; count < size; ++count)
std::cout << array[count] << ' '; // <- 부분적으로 나누어 특수화!
std::cout << endl;
}
template <int size>
void print(StaticArray<char, size> &array)
{
for (int count = 0; count < size; ++count)
std::cout << array[count]; // <- 숫자는 한칸씩 띄어지지만 글자는 붙은 형태로 출력!
std::cout << endl;
}
int main(void)
{
StaticArray<int, 4> int4;
int4[0] = 1;
int4[1] = 2;
int4[2] = 3;
int4[3] = 4;
print(int4);
StaticArray<char, 14> char14;
char14[0] = 'H';
char14[1] = 'e';
// ...
strcpy_s(char14.getArray(), 14, "Hello, World");
print(char14);
}
13.7 포인터에 대한 템플릿 특수화
#include <iostream>
using namespace std;
template<class T>
class A
{
private:
T m_value;
public:
A(const T &input)
: m_value(input)
{
}
void print()
{
cout << m_value << endl;
}
};
template<class T>
class A<T*>
{
private:
T* m_value;
public:
A(T *input)
: m_value(input)
{
}
void print()
{
cout << *m_value << endl;
}
};
int main(void)
{
A<int> a_int(123);
a_int.print();
int temp = 456;
A<int *> a_int_ptr(&temp);
a_int_ptr.print();
double temp_d = 3.141592;
A<double *> a_double_ptr(&temp_d);
a_double_ptr.print();
return (0);
}
13.8 맴버 함수를 한번 더 템플릿화 하기 templatize
#include <iostream>
using namespace std;
template<class T>
class A
{
private:
T m_value;
public:
A(const T &input)
: m_value(input)
{
}
template<typename TT>
void doSomething(const TT &input)
{
cout << typeid(T).name() << " " << typeid(TT).name() << endl;
}
void print()
{
cout << m_value << endl;
}
};
int main(void)
{
A<int> a_int(123);
a_int.doSomething<float>(123.4);
a_int.doSomething('a');
return (0);
}
Author And Source
이 문제에 관하여([따배C++] 13. 템플릿), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://velog.io/@24siefil/따배C-13.-템플릿
저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
#include <iostream>
#include <array>
using namespace std;
template<typename T>
class A
{
public:
A(const T& input)
{}
void doSomething()
{
cout << typeid(T).name() << endl;
}
void test()
{}
};
template<>
class A<char>
{
public:
A(const char & temp);
void doSomething()
{
cout << "Char type specialization" << endl;
}
};
int main(void)
{
A<int> a_int(1);
A<double> a_double(3.14);
A<char> a_char('a');
a_int.doSomething();
a_double.doSomething();
a_char.doSomething();
}
#include <iostream>
#include <string.h>
using namespace std;
template <class T, int size>
class StaticArray
{
private:
T m_array[size];
public:
T * getArray() { return (m_array); }
T &operator[](int index)
{
return (m_array[index]);
}
};
template <typename T, int size>
void print(StaticArray<T, size> &array)
{
for (int count = 0; count < size; ++count)
std::cout << array[count] << ' '; // <- 부분적으로 나누어 특수화!
std::cout << endl;
}
template <int size>
void print(StaticArray<char, size> &array)
{
for (int count = 0; count < size; ++count)
std::cout << array[count]; // <- 숫자는 한칸씩 띄어지지만 글자는 붙은 형태로 출력!
std::cout << endl;
}
int main(void)
{
StaticArray<int, 4> int4;
int4[0] = 1;
int4[1] = 2;
int4[2] = 3;
int4[3] = 4;
print(int4);
StaticArray<char, 14> char14;
char14[0] = 'H';
char14[1] = 'e';
// ...
strcpy_s(char14.getArray(), 14, "Hello, World");
print(char14);
}
13.7 포인터에 대한 템플릿 특수화
#include <iostream>
using namespace std;
template<class T>
class A
{
private:
T m_value;
public:
A(const T &input)
: m_value(input)
{
}
void print()
{
cout << m_value << endl;
}
};
template<class T>
class A<T*>
{
private:
T* m_value;
public:
A(T *input)
: m_value(input)
{
}
void print()
{
cout << *m_value << endl;
}
};
int main(void)
{
A<int> a_int(123);
a_int.print();
int temp = 456;
A<int *> a_int_ptr(&temp);
a_int_ptr.print();
double temp_d = 3.141592;
A<double *> a_double_ptr(&temp_d);
a_double_ptr.print();
return (0);
}
13.8 맴버 함수를 한번 더 템플릿화 하기 templatize
#include <iostream>
using namespace std;
template<class T>
class A
{
private:
T m_value;
public:
A(const T &input)
: m_value(input)
{
}
template<typename TT>
void doSomething(const TT &input)
{
cout << typeid(T).name() << " " << typeid(TT).name() << endl;
}
void print()
{
cout << m_value << endl;
}
};
int main(void)
{
A<int> a_int(123);
a_int.doSomething<float>(123.4);
a_int.doSomething('a');
return (0);
}
Author And Source
이 문제에 관하여([따배C++] 13. 템플릿), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://velog.io/@24siefil/따배C-13.-템플릿
저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
#include <iostream>
using namespace std;
template<class T>
class A
{
private:
T m_value;
public:
A(const T &input)
: m_value(input)
{
}
void print()
{
cout << m_value << endl;
}
};
template<class T>
class A<T*>
{
private:
T* m_value;
public:
A(T *input)
: m_value(input)
{
}
void print()
{
cout << *m_value << endl;
}
};
int main(void)
{
A<int> a_int(123);
a_int.print();
int temp = 456;
A<int *> a_int_ptr(&temp);
a_int_ptr.print();
double temp_d = 3.141592;
A<double *> a_double_ptr(&temp_d);
a_double_ptr.print();
return (0);
}
#include <iostream>
using namespace std;
template<class T>
class A
{
private:
T m_value;
public:
A(const T &input)
: m_value(input)
{
}
template<typename TT>
void doSomething(const TT &input)
{
cout << typeid(T).name() << " " << typeid(TT).name() << endl;
}
void print()
{
cout << m_value << endl;
}
};
int main(void)
{
A<int> a_int(123);
a_int.doSomething<float>(123.4);
a_int.doSomething('a');
return (0);
}
Author And Source
이 문제에 관하여([따배C++] 13. 템플릿), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@24siefil/따배C-13.-템플릿저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)