본문 바로가기
Language/C++

13.제네릭 프로그래밍

by 아무키 2023. 12. 25.
반응형

제네릭 프로그래밍

 

→ 타입에 관계없이 동작하는 일반적인 코드를 작성하는 방법

ex) 여러가지 덧셈을 수행하는 함수들을 작성할 때, 아래와 같은 함수들을 개별적으로 구현해야 했다.

→ add(int, int) / add(double, double/ add(Point, Point)

이를 한번의 코드 작성으로 가능하게 하는 방법이 제네릭 프로그래밍 기법

 

제네릭 프로그래밍의 구현 방법

매크로 사용 ← 사용시 주의

함수 / 클래스 템플릿 사용

 

매크로 ( #define)

#define MAX_SIZE 100
#define PI 3.141592

//전처리후 PI는 3.141592로 바뀜

doule a = PI * 3; //--->  double a = 3.141592 * 3;

 

 

Generic 하지 않은 프로그래밍

int 타입에 대한 max함수의 구현

int max(int a, int b){
	return (a > b) ? a : b;
}

int x = 100, y = 200;

cout << max(x, y); // 200

 

double, char 타입으로 확장하려면 추가적인 구현이 필요

→ 암시적 형 변환을 통해 추가 구현하지 않아도 가능한 경우가 있으나 제한적

 

매크로를 사용한 max함수의 일반적인 구현

매크로에 인수(a, b)를 정의해 줄 수 있다.

#define MAX(a, b) ((a > b) ? a : b)

cout << MAX(10, 20); // 20
cout << MAX(2.4, 3.5); // 3.5
cout << MAX('A', 'C'); //C

 

매크로를 사용할 때의 유의사항

코드가 단순 대체됨에 유의

매크로문을 괄호로 감싸는 것이 안전

매크로는 디버깅이 불편, namespace가 없어서 전역범위로 부작용 우려

#define SQUARE(a) a*a

result = SQUARE(5); // 25
result = 5 * 5; // 25

result = 100/SQUARE(5); // 4?
result = 100/5*5; // 100
#define SQUARE(a) ((a)*(a))

result = SQUARE(5); // 25
result = 5 * 5; // 25

result = 100/SQUARE(5); // 4
result = 100/((5)*(5)); // 4

 

C++ 템플릿 (Generic Programming using Template)

설계도 개념

함수 템플릿과 클래스 템플릿 구현을 지원

어떤 데이터 타입이든, 컴파일러가 적절한 함수 / 클래스를 설계도를 기반을 생성

→ 다른 언어의 경우 런타임에 생성하는 경우도 있다.

→ 사용하지 않는 경우 생성하지 않음

제네릭 프로그래밍 / 메타 프로그래밍

 

템플릿을 사용한 max함수의 구현

1. 타입명을 T로 대체

2. T가 템플릿 인수라는 것을 명시

→ template <typename T> or template < class T>

→ 꼭 T를 써야하는 것은 아니지만 일반적으로 많은 개발자들이 T를 우선적으로 사용

int max(int a, int b){
	return (a > b)? a: b;
}

//------------------>
//위를 아래로 변경

#include<ioatream>

template <typename T>

T max(T a, T b){
	return (a > b)? a: b;
}

int main(){
		int a = 10, b = 20;
		double c = 1.234, d = 34.5;

		std::cout << max<int>(a, b) << std::endl;;
		sotd::cout << max<double>(a, b) << std::endl;
}

 

템플릿 함수를 사용할 때는 자료형을 < > 안에 명시

→ 컴파일러가 타입을 추론 가능할 때는 생략 가능

호출할 타입이 결정되면, 컴파일러가 템플릿을 기반으로 실제 함수를 생성

→ 템플릿 코드만 존재할 때는 아무 함수도 생성되지 않음, 실제 사용이 되어야 코드가 생성

 

템플릿이 사용 가능한 경우

max함수의 경우 >가 정의되어 있어야 (a > b)가 연산 가능

즉, 클래스의 경우 필요한 연산자가 오버로딩되어 있어야 템플릿 max함수 사용 가능

template <typename T>

T max(T a, T b){
	return (a > b)? a: b;
} //(a > b)의 결과를 계산할 수 있어야만 함수 본문이 실행 가능

Player p1{"Kim", 100, 20}
Player p2{"Ha", 100, 30}

cout << max<Player>(p1, p2);
//Player 클래스에 대해 operator>가 오버로딩 되어 있지 않다면
//컴파일 오류 발생

 

템플릿의 다중 매개변수

서로 다른 이름을 사용하여 다중 매개변수를 정의 가능

매개변수가 다르다면 서로 타입이 다를 수 있다.

template <typename T1, typename T2>

void func(T1 a, T2 b){
	cout << a << ' ' << b;
}

func<int, double> (10, 20.55);
//T1은 int, T2는 double인 func함수 생성
func('A', 12.4);
//T1은 char이고 T2가 double인 것이 명확
//해당하는 함수 생성

 

템플릿의 특수화

특정 자료형에 대해서는 템플릿을 사용하지 않고 별도 구현한 함수를 사용하도록 명시 가능

template <typename T>

T min(T a, T b){
	return (a < b)? a: b;
}

template<> 
// std::string type의 인자에 대해서 사용하는
// 명시적 특수화

std::string min(std::string a, std::string b){
	return (a.length() < b.length())? a: b;
}

 

클래스 템플릿

함수 템플릿과 유사한 클래스에 대한 템플릿 구현 지원 ..클래스의 설계도

컴파일러가 타입에 따라 적절한 클래스를 생성해 줌

 

클래스 템플릿, Item 클래스 예제

class Item{
	private:
		string name;
		int value;
	public:
		Item(string name, int value)
			:name{name}, value{value}{}
		string getName() const {return name;}
		int getValue() const {return value;}
};

int main(){
		Item i{"A"}, 10};
		std::cout << i.GetName() << st::endl;
		std::cout << i.GetValue() << std::endl;

 

클래스 템플릿의 정의

template <template T>

class Item{
	private:
		string name;
		T value;
	public:
		Item(string name, T value)
			:name{name}, value{value}{}
		string getName() const{return name;}
		T getValue() const {return valeu;}
};

int main(){
	Item<int> i{"A", 10};
	std:cout << i.GetName() << std::endl;
	std::cout << i.GetValue() << std::endl;

	Item<double> d{"B", 1.345};
	std::cout << d.GetName() << std::endl;
	std:cout << d.GetValue() << std::endl;
}

 

클래스 템플릿의 사용

함수처럼 타입을 적지 않아도 타입을 추론하는 기능이 C++ 17 추가

Item item1 {"Kim", 1}; //Item<int>로 추론
Item item2 {"Lee", 10.5}; //Item<double>로 추론
Item item3 {"Park", "hello"}; //Item<std::string>으로 추론

 

vs17 프로젝트 속성 → C/C++ → 언어 → C++ 언어 표준 C++17변경

 

클래스 템플릿의 다중 매개변수

선언과 사용

template <typename T1, typename T2>

class MyPair{
	private:
		T1 first;
		T2 second;
	public:
		MyPair(T1 vall, T2 vall)
			:first{vall}, second{vall}{}
};

MyPair<string, int>p1{"Kim", 1};
MyPair<int, double>p2{123, 45.6};

 

클래스 템플릿의 (부분)특수화

class classname<type 명시>

template<typename T1, typename T2>

class Item{
	private:
		T1 key;
		T2 value;
	public:
		...
};

template<typename T>

class Item<T, double> // value가 double형 일때 클래스 템플릿의 특수화
	private:
		T key;
		double value;
	public:
		...
};

 

클래스 템플릿 매개변수

타입이 아닌 다른 매개변수를 사용할 수 있다

(non-type template argument)

→ 아래 예시에서 N의 값을 클래스의 사용시에 직접 명시해 줌

template<typaname T, int N>

class Array{
		int size = N;
		T values[N}; //정적 배일이기 때문에 고정된 크기 필요
		...


int main(){
		Array<int ,5> nums;
		Arary<double, 10> nums2;
		...
}

//두 개의 클래스를 만들어 냄
class Array<int ,5>{
		int size = 5;
		int values[5];
		...

class Array<double, 10>{
		int size = 10;
		double values[10];
		...
반응형

'Language > C++' 카테고리의 다른 글

15.STL Containers  (0) 2023.12.25
14.STL  (1) 2023.12.25
12.연산자 오버로딩  (1) 2023.12.25
11.다형성  (1) 2023.12.25
10.상속  (0) 2023.12.23

댓글