티스토리 뷰
반응형
추가되는 기능
- 사용되는 타입이 다른 타입으로도 같은 수행이 보장되어 일반화할 수 있을 때 template을 사용한다.
int add(int a, int b) { return a + b; } float add(float a, float b) { return a + b; } int sum_int = add(10, 20); // = 30 float sum_float = add(10.5f, 20.5f); // = 31
template<typename T> T add(T a, T b) { return a + b; } int sum_int = add(10, 20); float sum_float = add(10.5f, 20.5f);
template을 사용할 경우 코드의 재사용성이 높아지며 같은 코드를 반복적으로 작성할 필요가 없어진다. 이때 필요한 타입에 대한 추론이 컴파일러에 의해 실행되며 각 사용에 맞는 타입의 함수로 생성된다.
- Class 또는 구조체에 대해서도 template을 적용할 수 있다. 또한 class와 구조체도 template의 인자로 쓰일 수 있다.
#include <iostream> template<typename T> class holder { private: T data; public: T get() const { return data; } void set(T data) { this->data = data; } }; int main() { holder<int> holder_i; holder_i.set(10); std::cout << holder_i.get() << std::endl; holder<holder<int>> holder_holder_i; holder_holder_i.set(holder_i); std::cout << holder_holder_i.get().get() << std::endl; return 0; }
Template에도 기본값을 정할 수 있다. 기본값이 주어졌고 호출에서 명시적 선언이 없다면 기본값을 사용하게 된다.
#include <iostream> template<typename T = int> class holder { private: T data; public: T get() const { return data; } void set(T data) { this->data = data; } }; int main() { holder holder_i; holder_i.set(10); std::cout << holder_i.get() << std::endl; return 0; }
- 함수 템플릿에서 타입이 모호할 경우 명시적으로 타입을 지정해줄 수 있다.
#include <iostream> #include <string> template<typename T> T add(T a, T b) { return a + b; } int main() { std::cout << add(10, 20) << std::endl; std::cout << add<std::string>("Hello", "World") << std::endl; return 0; }
30 HelloWorld
C++에서는 string literal을 const char*로 처리하기때문에 덧셈 이항 연산자(operator+)를 이용하여 char*간 연산이 불가능하다. 따라서 명시적으로 std::string임을 지정해 두 string literal을 이은 결과를 반환할 수 있다.
- Template은 타입뿐만 아니라 compile-time constant에 대해서도 정의할 수 있다. constexpr 기호를 이용하여 외부 변수로 상수를 정의할 때, 해당 코드를 수정할 수 없다면 외부에서 고정된 값을 사용해야하므로 이 방법을 사용하는 것이 좋다. 또한, 기본값을 정할 수 있으므로 상수로의 역할도 똑같이 실행할 수 있으므로 되도록 #define과 constexpr을 이용하여 객체의 가변 상수를 지정하는 방법을 피하자.
#include <iostream> template<typename T = int, T INITIAL = 10> class holder { private: T data = INITIAL; public: T get() const { return data; } void set(T data) { this->data = data; } }; int main() { holder<int, 100> holder_i; std::cout << holder_i.get() << std::endl; return 0; }
목표
- 반복되어 사용되고 대체될 수 있는 타입에 대해 템플릿을 적용한다.
- 외부에서 지정할 수 있는 기본값에 대해 템플릿을 적용한다.
디자인
- class vector에 다음 템플릿 인자를 추가한다.
- typename T
- int INITIAL_SIZE = 10
- 다음 함수의 선언이 템플릿 인자로 바뀐다.
- void add(int) => void add(T)
- void add(int, int) => void add(int, T)
- int get(int) => T get(int)
- int set(int, int) => T set(int, T)
- int remove(int) => T remove(int)
- vector& operator+=(int) => vector& operator+=(T)
구현
#include <iostream>
#include <algorithm>
template<typename T, int INITIAL_SIZE = 10>
class vector {
private:
T* data;
int capacity;
int length;
bool ensure_capacity(int to_add) const {
return length + to_add < capacity;
}
void increase_capacity() {
auto tmp = data;
data = new T[capacity * 2];
std::copy(tmp, tmp + length, data);
delete[] tmp;
capacity *= 2;
}
void shiftLeft(int offset, int width) {
int tail_length = length - offset - width;
T* tail = new T[tail_length];
std::copy(data + offset + width, data + length, tail);
std::copy(tail, tail + tail_length, data + offset);
delete[] tail;
}
void shiftRight(int offset, int width) {
int tail_length = length - offset;
T* tail = new T[tail_length];
std::copy(data + offset, data + length, tail);
std::copy(tail, tail + tail_length, data + offset + width);
delete[] tail;
}
public:
vector() {
data = new T[INITIAL_SIZE];
capacity = INITIAL_SIZE;
length = 0;
}
vector(const vector& v) {
data = new T[v.capacity];
capacity = v.capacity;
length = v.length;
std::copy(v.data, v.data + v.length, data);
}
~vector() {
delete[] data;
}
void add(T element) {
if (!ensure_capacity(1))
increase_capacity();
*(data + length++) = element;
}
void add(int index, T element) {
if (!ensure_capacity(1))
increase_capacity();
shiftRight(index, 1);
*(data + index) = element;
length++;
}
T get(int index) const {
return *(data + index);
}
T set(int index, T element) {
auto tmp = *(data + index);
*(data + index) = element;
return tmp;
}
T remove(int index) {
auto tmp = *(data + index);
shiftLeft(index, 1);
length--;
return tmp;
}
void print() const {
std::cout << '{';
for (int i = 0; i < length; i++)
std::cout << *(data + i) << ((i < length - 1) ? ", " : "");
std::cout << '}' << std::endl;
}
vector& operator=(const vector& v) {
data = new T[v.capacity];
capacity = v.capacity;
length = v.length;
std::copy(v.data, v.data + capacity, data);
return *this;
}
vector& operator+=(T element) {
add(element);
return *this;
}
T& operator[](int index) {
return *(data + index);
}
T operator[](int index) const {
return *(data + index);
}
};
반응형
'C++ > C to C++' 카테고리의 다른 글
[C to C++] 상속 - 생존주기, 가상함수 (0) | 2019.02.02 |
---|---|
[C to C++] 상속 (0) | 2019.02.01 |
[C to C++] friend, 연산자 오버로딩 (0) | 2019.01.31 |
[C to C++] 함수 오버로딩 (0) | 2019.01.31 |
[C to C++] 생성자, 소멸자, 복사 생성자 (0) | 2019.01.29 |
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- dokdo 4.0.3
- c++11
- dokdo project
- CM10.2
- rule_of_three
- d802
- c++ struct
- f320k
- g2 korea
- rule_of_five
- C++ 업캐스팅
- Kotlin
- PipelineContext
- LG
- OOP
- C
- Java
- 포인터
- dokdo-project
- G2
- cyanogenmod
- c++ 상속
- nodeal
- f320s
- linaro
- CM11
- 객체지향
- vector
- C++
- inline class
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함