C++/Templates
2021. 3. 21. 23:59
클래스 템플릿 (Class Templates)
- 클래스에도 템플릿을 적용할 수 있다.
예제
템플릿을 사용하지 않은 예제
main.cpp
#include "MyArray.h" int main() { MyArray my_array(10); for (int i = 0; i < my_array.getLength(); ++i) my_array[i] = i * 10; my_array.print(); } /* stdout 0 10 20 30 40 50 60 70 80 90 */
MyArray.h
#pragma once #include <iostream> #include <cassert> class MyArray { int length_; int* data_; public: MyArray() { length_ = 0; data_ = nullptr; } MyArray(const int& length_in) { data_ = new int[length_in]; length_ = length_in; } ~MyArray() { reset(); } void reset() { delete[] data_; data_ = nullptr; length_ = 0; } int& operator[](int index) { assert(index >= 0 && index < length_); return data_[index]; } int getLength() { return length_; } void print() { for (int i = 0; i < length_; ++i) std::cout << data_[i] << ' '; std::cout << std::endl; } };
템플릿을 적용한 예제
main.cpp
#include "MyArray.h" int main() { MyArray<int> my_array(10); for (int i = 0; i < my_array.getLength(); ++i) my_array[i] = i * 10; my_array.print(); } /* stdout 0 10 20 30 40 50 60 70 80 90 */
MyArray.h
#pragma once #include <iostream> #include <cassert> template<typename T> class MyArray { int length_; T* data_; public: MyArray() { length_ = 0; data_ = nullptr; } MyArray(const int& length_in) { data_ = new T[length_in]; length_ = length_in; } ~MyArray() { reset(); } void reset() { delete[] data_; data_ = nullptr; length_ = 0; } T& operator[](int index) { assert(index >= 0 && index < length_); return data_[index]; } int getLength() { return length_; } void print() { for (int i = 0; i < length_; ++i) std::cout << data_[i] << ' '; std::cout << std::endl; } };
main.cpp
에서 다른 자료형을 넣어도 작동한다.#include "MyArray.h" int main() { MyArray<double> my_array(10); for (int i = 0; i < my_array.getLength(); ++i) my_array[i] = i * 0.5; my_array.print(); } /* stdout 0 0.5 1 1.5 2 2.5 3 3.5 4 4.5 */
#include "MyArray.h" int main() { MyArray<char> my_array(10); for (int i = 0; i < my_array.getLength(); ++i) my_array[i] = i + 65; my_array.print(); } /* stdout A B C D E F G H I J */
헤더 파일과 .cpp 파일의 분리
헤더에 함수를 정의했는데, 이를
.cpp
파일로 분리해야 한다.템플릿을 사용하면 이 과정이 살짝 번거롭다.
일단 헤더 파일에서만
print
함수를 분리해보면 다음과 같다.MyArray.h
#pragma once #include <iostream> #include <cassert> template<typename T> class MyArray { int length_; T* data_; public: MyArray() { length_ = 0; data_ = nullptr; } MyArray(const int& length_in) { data_ = new T[length_in]; length_ = length_in; } ~MyArray() { reset(); } void reset() { delete[] data_; data_ = nullptr; length_ = 0; } T& operator[](int index) { assert(index >= 0 && index < length_); return data_[index]; } int getLength() { return length_; } void print(); }; template<typename T> void MyArray<T>::print() { for (int i = 0; i < length_; ++i) std::cout << data_[i] << ' '; std::cout << std::endl; }
- 이대로 컴파일하면 아무 문제가 없다.
다음은
MyArray.cpp
파일로 옮기는 과정이다.헤더 파일에서 분리한 함수 정의 부분을 잘라내서,
.cpp
파일에 그대로 붙여넣기한다.MyArray.cpp
#include "MyArray.h" template<typename T> void MyArray<T>::print() { for (int i = 0; i < length_; ++i) std::cout << data_[i] << ' '; std::cout << std::endl; }
error LNK2019: unresolved external symbol "public: void __cdecl MyArray<char>::print(void)" (?print@?$MyArray@D@@QEAAXXZ) referenced in function main
main.cpp
에서MyArray.cpp
에 정의된 함수의body
내용을 알 수 없기 때문에 발생하는 문제라고 한다.- 템플릿의 작동 원리를 알아야 완벽하게 파악할 수 있을 것 같다.
main.cpp
에서MyArray.cpp
를include
하면 해결되긴 하는데, 이렇게 하는 것은 좋지 않다고 한다.대신
explicit instantiation
을 해야하는데, 명시적으로 템플릿을 적용하는 것이다.
Explicit Instantiation
클래스나 함수에 적용할 템플릿을 명시해주는 것이다.
MyArray.cpp
#include "MyArray.h" template<typename T> void MyArray<T>::print() { for (int i = 0; i < length_; ++i) std::cout << data_[i] << ' '; std::cout << std::endl; } template class MyArray<char>; template void MyArray<double>::print();
'C++ > Templates' 카테고리의 다른 글
C++ 클래스 템플릿 특수화 (Class Templates Specialization) (0) | 2021.03.22 |
---|---|
C++ 함수 템플릿 특수화 (Function Templates Specialization) (0) | 2021.03.22 |
C++ 자료형이 아닌 템플릿 매개변수 (Non-type Templates Parameters) (0) | 2021.03.21 |
C++ 함수 템플릿 (Function Templates) (0) | 2021.03.21 |
C++ 템플릿 (Templates) (0) | 2021.03.21 |