wn42
코딩이랑 이것저것
wn42
전체 방문자
오늘
어제
  • 분류 전체보기 (113)
    • 프로그래머스 (23)
      • LV1 (11)
      • LV2 (1)
      • LV3 (3)
      • 연습 (8)
    • 딥러닝 공부 (0)
      • 머신러닝&딥러닝 이론 (0)
    • 임베디드 (17)
      • Adventure Design (1)
      • 센서기반모바일로봇 (5)
      • ROS (9)
      • Google Coral (2)
    • C++ (38)
      • C++ 기초 (34)
      • 자료구조 및 알고리즘 (4)
    • Python (14)
      • 기본 파이썬 문법 (6)
      • Python 기초 (8)
    • 빅데이터 (9)
      • 빅데이터 첫걸음 시작하기(국비지원) (5)
      • 빅데이터 공부 (4)
    • 알고리즘 공부 (2)
      • 기본 알고리즘 (2)
    • 전자공학 (10)
      • 반도체 공정 (3)
      • 무선데이터통신 (7)
      • 반도체공학 (0)
    • C# (0)
      • C# 기본 (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 프로그래머스
  • 파이썬
  • 큐
  • 스택/큐
  • 클래스
  • ROS
  • K디지털크레딧
  • 스택
  • 인스턴스
  • 빅데이터 첫걸음 시작하기
  • 빅데이터
  • c++
  • numpy
  • 딥러닝
  • 변수
  • 상속
  • 데이터분석
  • Python
  • stl
  • 바이트디그리
  • 정렬
  • 반복문
  • 데이터분석 인강
  • google coral
  • Queue
  • 노드
  • 내일배움카드
  • 패스트캠퍼스
  • 소멸자
  • 조건문

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
wn42

코딩이랑 이것저것

C++/C++ 기초

[C++] 템플릿 (Template)

2023. 1. 29. 17:44

 템플릿 

매개변수의 타입에 따라 함수나 클래스를 생성하는 매커니즘

  • 여러 타입에서 동작할 수 있는 코드를 찍어내는 틀이라고 생각하면 된다.
  • 템플릿을 사용하면 다양한 타입에 대해서 하나의 함수만 정의하면 되므로 전체 코드를 매우 간결하게 만들 수 있다.
  • 템플릿을 통해 타입을 마치 인자인 것 마냥 사용하는 것을 일반화 프로그래밍(generic programming)이라고 한다.

 

템플릿 정의

  • 템플릿은 함수 템플릿(Function Template)과 클래스 템플릿(Class Template)으로 나뉜다.

함수 템플릿 정의

template <typename 타입이름>
함수 원형
{
    // 함수 본체
}
  • typename 키워드를 template의 인자로서 받는다.
  • 타입이름은 함수 원형과 본체에서 임의의 타입으로 사용되며, 함수 호출 시 전달된 매개변수 형에 맞춰 바뀐다.
  • typename 키워드 대신 class 키워드를 넣어도 같은 동작을 하지만, 대부분 typename 키워드를 이용한다.

 

클래스 템플릿 정의

template <typename 타입이름>
class 클래스템플릿이름
{
    // 클래스 멤버의 선언
}
  • 타입이름은 클래스에서 임의의 타입으로서 사용되며, 인스턴스 생성 시 전달된 매개변수 형에 맞춰 바뀐다.

 

 

함수 템플릿 사용하기

swap 함수 예제

#include <iostream>
using namespace std;

// 함수 템플릿 프로토타입
template <typename T>
void Swap(T& a, T& b);

int main() {
	int a = 10, b = 50;
	cout << "swap 이전 >> " << "a = " << a << ", b = " << b << endl;
	Swap(a, b);
	cout << "swap 이후 >> " << "a = " << a << ", b = " << b << endl;

	string c = "hello", d = "world";
	cout << "swap 이전 >> " << "c = " << c << ", d = " << d << endl;
	Swap(c, d);
	cout << "swap 이후 >> " << "c = " << c << ", d = " << d << endl;

	return 0;
}

// 함수 템플릿 정의
template <typename T>
void Swap(T& a, T& b) {
	T temp;
	temp = a;
	a = b;
	b = temp;
}
swap 이전 >> a = 10, b = 50
swap 이후 >> a = 50, b = 10
swap 이전 >> c = hello, d = world
swap 이후 >> c = world, d = hello
  • T라는 타입이름을 선언하여 매개변수의 값을 바꾸는 Swap 함수를 구현하였다.
  • 따로 함수에 매개변수 타입을 정의하지 않아도 T가 int형, string형 인자를 받음과 동시에 해당 타입으로 바뀌어 함수가 동작하였다.
  • 이렇게 함수를 함수 템플릿으로 정의하면 int형, string형 함수를 따로 구현할 필요없이 하나의 함수만 구현하면 되므로 매우 효율적으로 프로그램을 작성할 수 있다.

 

함수 템플릿의 명시적 특수화 (Explicit Specialization)

  • 같은 이름의 함수 템플릿 동작을 특정 타입에 대해서 다르게 설정할 수 있다.
#include <iostream>
using namespace std;

// 함수 템플릿 프로토타입
template <typename T>
void Swap(T& a, T& b);

// string 형에 대한 함수 템플릿 프로토타입
template <>
void Swap(string& a, string& b);	// string형 인자를 받음을 명시

int main() {
	int a = 10, b = 50;
	cout << "swap 이전 >> " << "a = " << a << ", b = " << b << endl;
	Swap(a, b);
	cout << "swap 이후 >> " << "a = " << a << ", b = " << b << endl;

	string c = "hello", d = "world";
	cout << "swap 이전 >> " << "c = " << c << ", d = " << d << endl;
	Swap(c, d);
	cout << "swap 이후 >> " << "c = " << c << ", d = " << d << endl;

	return 0;
}

// 함수 템플릿 정의
template <typename T>
void Swap(T& a, T& b) {
	T temp;
	temp = a;
	a = b;
	b = temp;
}

// string형에 대한 함수 템플릿 정의
template <>	// 동작을 하지 않을 것이므로 typename을 지정하지 않았음
void Swap(string& a, string& b) {
	// 아무것도 하지 않는다.
}
swap 이전 >> a = 10, b = 50
swap 이후 >> a = 50, b = 10
swap 이전 >> c = hello, d = world
swap 이후 >> c = hello, d = world

 

 

클래스 템플릿 사용하기

  • 함수 템플릿을 호출할 때와 달리 클래스 템플릿을 사용할 때는 반드시 타입을 명시해야 한다. ▶이는 클래스의 생성자가 호출되기 이전에 멤버 변수의 타입을 확인하여, 객체의 메모리 공간을 할당해야 할 필요가 있기 때문이다.
  • 타입을 인자로 전달하게 되면, 이후 컴파일러가 이를 확인하고 실제 코드를 생성한다. ▶ 이를 클래스 템플릿 인스턴스화(class template instantiation)라고 한다.

클래스 템플릿 특징

  1. 하나 이상의 인자를 가진다. ▶ template <typename T, int i> 는 2개의 템플릿 인자를 가짐.
  2. 디폴트 템플릿 인자를 명시할 수 있다. ▶ template <typename T=int> 는 디폴트 템플릿 인자가 int
  3. 기초 클래스로 상속할 수 있다. 아래는 예시.
// 기초 클래스
template <typename T>
class XClass {

};

// 상속
template <typename Type>
class YClass : public XClass<Type> {
	// 
};

 

숫자를 2배 곱하는 클래스 예제

#include <iostream>
using namespace std;

template <typename T>
class MyClass {
private:
	T x;
public:
	MyClass(T _x);
	T Caldouble();
};

int main(void) {
	MyClass<int> int_(10);	// 인스턴스화 할 때 반드시 타입을 명시해야 함
	MyClass<double> double_(1.2345);

	cout << "int_ * 2 = " << int_.Caldouble() << endl;
	cout << "double_ * 2 = " << double_.Caldouble() << endl;
	return 0;
}

template <typename T>
MyClass<T>::MyClass(T _x) {
	x = _x;
}

template <typename T>
T MyClass<T>::Caldouble() {
	return x * 2;
}
int_ * 2 = 20
double_ * 2 = 2.469
  • 함수 템플릿을 호출할 때와 달리 MyClass<type> 처럼 타입을 반드시 명시하여 전달해야 함에 유의한다.
  • 타입을 명시하지 않을 시 다음과 같은 오류들이 발생한다.

 

클래스 템플릿 명시적 특수화

#include <iostream>
using namespace std;

// 클래스 템플릿
template <typename T>
class MyClass {
private:
	T x;
public:
	MyClass(T _x);
	T Caldouble();
};

// double 형에 대한 명시적 특수화
template <>
class MyClass<double> {
private:
	double x;
public:
	MyClass(double _x) { x = _x; }
	double Caldouble() {
		cout << "double 형 데이터를 2배하여 출력합니다. " << endl;
		return x * 2;
	};
};

int main(void) {
	MyClass<int> int_(10);
	MyClass<float> float_(5.12f);
	MyClass<double> double_(1.2345);

	cout << "int_ * 2 = " << int_.Caldouble() << endl << endl;
	cout << "float_ * 2 = " << float_.Caldouble() << endl << endl;
	cout << "double_ * 2 = " << double_.Caldouble() << endl << endl;
	return 0;
}

template <typename T>
MyClass<T>::MyClass(T _x) {
	x = _x;
}

template <typename T>
T MyClass<T>::Caldouble() {
	cout << "데이터를 2배하여 출력합니다. (double형 제외)" << endl;
	return x * 2;
}
데이터를 2배하여 출력합니다. (double형 제외)
int_ * 2 = 20

데이터를 2배하여 출력합니다. (double형 제외)
float_ * 2 = 10.24

double 형 데이터를 2배하여 출력합니다.
double_ * 2 = 2.469
  • double 형에 대한 클래스의 명시적 특수화를 구현하였다.
  • double 형을 제외한 데이터 형들은 첫 번째의 클래스로 인스턴스를 생성하며, double 형은 두 번째 클래스로 인스턴스를 생성한다. ▶ 컴파일러는 전달된 인수에 대응하는 정의를 먼저 찾고, 발견 시 해당 정의를 사용한다.
  • 다음과 같이 여러 인자가 있을 때 부분적으로 특수화를 구현할 수 있다.
// 3개의 인자를 가지는 클래스 템플릿 예

// 일반적인 클래스 템플릿
template <typename A, typename B, typename C>
class MyClass {};

// 첫 번째 인자에 대한 특수화 - A가 int일 경우
template <typename B, typename C>
class MyClass<int> {};

// 첫 번째, 세 번째 인자에 대한 특수화 - A가 int, C가 double일 경우
template <typename B>
class MyClass<int, B, double> {};

// 모든 인자에 대한 특수화 - A가 int, B가 int, C가 double일 경우
template <>
class MyClass<int, int, double> {};
    'C++/C++ 기초' 카테고리의 다른 글
    • [C++] 템플릿 응용
    • [C++] 순수 가상 함수 / 추상 클래스
    • [C++] virtual 소멸자
    • [C++] 클래스 상속 (Inheritance)
    wn42
    wn42
    코딩이랑 이것저것 하는 블로그

    티스토리툴바