제네릭 프로그래밍
→ 타입에 관계없이 동작하는 일반적인 코드를 작성하는 방법
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 |
댓글