for Robot Artificial Inteligence

19. Class-Templates & Typedef

|

Templates

  • 템플릿(template)이란 매개변수의 타입에 따라 함수나 클래스를 생성하는 메커니즘을 의미합니다.
  • 템플릿은 타입이 매개변수에 의해 표현되므로, 매개변수화 타입(parameterized type)이라고도 불립니다
  • 템플릿을 사용하면 타입마다 별도의 함수나 클래스를 만들지 않고, 여러 타입에서 동작할 수 있는 단 하나의 함수나 클래스를 작성하는 것이 가능합니다.

2. Function Template(함수 템플릿)

  • C++에서 함수 템플릿(function template)이란 함수의 일반화된 선언을 의미합니다
  • 함수 템플릿을 사용하면 같은 알고리즘을 기반으로 하면서, 서로 다른 타입에서 동작하는 함수를 한 번에 정의할 수 있습니다.
  • 임의의 타입으로 작성된 함수에 특정 타입을 매개변수로 전달하면, C++ 컴파일러는 해당 타입에 맞는 함수를 생성해 줍니다

문법 ``` template

함수의 원형

{

// 함수의 본체

}


- 위에서 정의된 타입 이름은 함수의 원형과 본체에서 임의의 타입으로 사용할 수 있습니다
- **이렇게 정의된 함수 템플릿을 호출할 때 매개변수로 int형을 전달하면, 함수의 원형과 본체에서 정의된 타입 이름은 모두 int형으로 바뀌게 됩니다.**

> 예제

template

void Swap(T& a, T& b);

int main(void)

{

int c = 2, d = 3;

cout << "c : " << c << ", d : " << d << endl;

Swap(c, d);

cout << "c : " << c << ", d : " << d << endl;



string e = "hong", f = "kim";

cout << "e : " << e << ", f : " << f << endl;

Swap(e, f);

cout << "e : " << e << ", f : " << f << endl;

return 0;

}

template

void Swap(T& a, T& b)

{

T temp;

temp = a;

a = b;

b = temp;

}


> 실행 결과

c : 2, d : 3

c : 3, d : 2

e : hong, f : kim

e : kim, f : hong


- 함수 템플릿이 각각의 타입에 대해 처음으로 호출될 때, C++ 컴파일러는 해당 타입의 인스턴스를 생성합니다.
- 이렇게 생성된 인스턴스는 해당 타입에 대해 특수화된 템플릿 함수입니다.
- 이 인스턴스는 함수 템플릿에 해당 타입이 사용될 때마다 호출됩니다.

## 3. 명시적 특수화(explicit specialization)
- C++의 함수 템플릿은 특정 타입에 대한 명시적 특수화를 제공하여, 해당 타입에 대해 특별한 동작을 정의할 수 있게 해줍니다.
- 컴파일러는 호출된 함수에 정확히 대응하는 특수화된 정의를 발견하면, 더는 템플릿을 찾지 않고 해당 정의를 사용합니다.
- 앞서 정의된 함수 템플릿 Swap의 double형에 대한 명시적 특수화는 다음과 같습니다.

> 함수 템플릿 원형

template

void Swap(T& a, T& b);

template void Swap(T& a, T& b);


> double형을 위한 명시적 특수화

template <> void Swap(double&, double&) { ... };


# [Typedef](https://wikidocs.net/419)
- typedef는 새로운 타입을 만드는 것이 아니라 타입의 새로운 별칭을 정의하는 키워드 입니다

typedef int TypedefInt; TypedefInt a;


- 이 키워드가 템플릿과 무슨 관계인지 설명하겠습니다
- typedef는 클래스 안에서 타입의 새로운 별칭을 지을 수 있습니다

class MyTypeClass { public: typedef int Type1; }; int main() { MyTypeClass a; MyTypeClass::Type1 b; return 0; }

- a는 MyTypeClass의 객체, b는 int 변수

class MyTypeClass { public: typedef int Type1; private: typedef double Type2; }; int main() { MyTypeClass a; MyTypeClass::Type1 b; MyTypeClass::Type2 c; //에러 return 0; }


class MyTypeClass { public: typedef int Type1; void f() { Type2 c; } private: typedef double Type2; }; int main() { MyTypeClass a; MyTypeClass::Type1 b; return 0; }

- typedef은 클래스 안에서도 타입의 별칭을 만들 수 있을 뿐 아니라 외부접근 제한 까지 영향을 받습니다.
- typedef는 템플릿 파라미터로 받은 데이터 타입이 필요할 때가 있습니다

#include

template class MyTempClass { public: typedef T TempType; }; int main() { MyTempClass a; MyTempClass::TempType b; MyTempClass c; MyTempClass::TempType d; return 0; }

- 이렇게 타입안에 타입의 객체를 호출 할 수 있습니다. **이렇게 템플릿 매개변수에 종속된 것을 의존 이름(dependent name)** 이라고 합니다
- 클래스안에 중첩된 경우가 있는데 **중첩 의존 이름(nested dependent name)** 이라고 합니다.
- 확히 하면 클래스 안에 TempType 이라는 타입이 있으니까 **중첩 의존 타입 이름(nested dependent type name)** 이라고 합니다.

# Exercise 1

> main.cpp

#include #include "point.h"

using namespace std; /* function templates generalization*/

void operationOnPoints();

template<typename T, typename T2> T add(T var1, T2 var2) { return var1 + var2; } /* template<> Point2D add(Point2D var1, Point2D var2) { Point2D tmp;

tmp.setX(var1.getX() + var2.getX());
tmp.setY(var1.getY() + var2.getY());

return tmp; } */ typedef Point<int> PointInt; int main() {
operationOnPoints();

//cout << add<double, double>(2, 5.6) << endl;

// cout « static_cast(6.5) << endl;

return 0; } void operationOnPoints() {  //   PointInt a(5);
Point<int*> b(49);

//cout << a.getX() << endl;
//cout << b.getX() << endl; }

> point.h

#ifndef POINT_H_INCLUDED #define POINT_H_INCLUDED #include

using namespace std;

template class Point //base, parent, superclass { protected: T x; public: Point(T =0); ~Point(); T getX(); void setX(T); }; template Point::Point(T x) { this->x = x; cout << "The constructor from the Point class has just been invoked" << endl; } template Point::~Point() { cout << "The destructor from the Point class has just been invoked" << endl; } template void Point::setX(T x) { this->x = x; cout << "Im from Point" << endl; } template T Point::getX() { return this->x; } template<> double Point::getX() { cout <<"this function will be executed only when Point" << endl; return this->x; }

template class Point<K*> { public: Point(K a=0) { cout << "you can't use pointers here"; } };

template class Point2D : public Point //derived, child, subclass { protected: T y; public: Point2D(T =0, T =0); ~Point2D(); T getY() { return y; } void setY(T); void setX(T); void setXY(T, T); Point2D operator+(Point2D);

}; template Point2D::Point2D(T x, T y) : Point(x) { this->y = y; cout << "The constructor from the Point2D class has just been invoked" << endl; } template Point2D::~Point2D() { cout << "The destructor from the Point2D class has just been invoked" << endl; } template void Point2D::setY(T y) { this->y = y; } template void Point2D::setXY(T x, T y) { setX(x); setY(y); } template void Point2D::setX(T x) { this->x = x; cout << "Im from Point2D" << endl; } template Point2D Point2D::operator+(Point2D o) { Point2D tmp;

tmp.setX(this->getX() + o.getX());
tmp.setY(this->getY() + o.getY());

return tmp; } /* class Point3D : public Point2D {

}; */

template<> class Point { public: Point(char a=0) { cout << "this is from Point";} }; /* class Point2D : public Point everything what is inside Point (excluding constructor and destructor) will be in Point2D private - CANNOT ACCESS protected - protected public - public

class Point2D : protected Point
everything what is inside Point (excluding constructor and destructor) will be in Point2D
private - CANNOT ACCESS
protected - protected
public - protected


class Point2D : private Point
everything what is inside Point (excluding constructor and destructor) will be in Point2D
private - CANNOT ACCESS
protected - private
public - private

*/ #endif // POINT_H_INCLUDED


# Exercise 2

> main.cpp

#include #include "point.h"

using namespace std; /* function templates generalization*/

void operationOnPoints();

template<typename T, typename T2> T add(T var1, T2 var2) { return var1 + var2; } /* template<> Point2D add(Point2D var1, Point2D var2) { Point2D tmp;

tmp.setX(var1.getX() + var2.getX());
tmp.setY(var1.getY() + var2.getY());

return tmp; } */ int main() {
operationOnPoints();

//cout << add<double, double>(2, 5.6) << endl;

// cout « static_cast(6.5) << endl;

return 0; } void operationOnPoints() {
Point2D p1(10, 67);
Point2D p2(50, 3); // 60,70

Point2D sum = add(p1,p2);

cout << sum.getX() << endl;
cout << sum.getY() << endl;

}


> point.h

#ifndef POINT_H_INCLUDED #define POINT_H_INCLUDED

class Point //base, parent, superclass { protected: int x; public: Point(int =0); ~Point(); int getX() { return x; } void setX(int); }; class Point2D : public Point //derived, child, subclass { protected: int y; public: Point2D(int =0, int =0); ~Point2D(); int getY() { return y; } void setY(int); void setX(int); void setXY(int, int); Point2D operator+(Point2D);

}; class Point3D : public Point2D {

};

/* class Point2D : public Point everything what is inside Point (excluding constructor and destructor) will be in Point2D private - CANNOT ACCESS protected - protected public - public

class Point2D : protected Point
everything what is inside Point (excluding constructor and destructor) will be in Point2D
private - CANNOT ACCESS
protected - protected
public - protected


class Point2D : private Point
everything what is inside Point (excluding constructor and destructor) will be in Point2D
private - CANNOT ACCESS
protected - private
public - private

*/ #endif // POINT_H_INCLUDED


> point.cpp

#include #include "point.h"

using namespace std;

Point::Point(int x) { this->x = x; cout « “The constructor from the Point class has just been invoked” « endl; } Point::~Point() { cout « “The destructor from the Point class has just been invoked” « endl; } void Point::setX(int x) { this->x = x; cout « “Im from Point” « endl; }

Point2D::Point2D(int x, int y) : Point(x) { this->y = y; cout « “The constructor from the Point2D class has just been invoked” « endl; } Point2D::~Point2D() { cout « “The destructor from the Point2D class has just been invoked” « endl; }

void Point2D::setY(int y) { this->y = y; } void Point2D::setXY(int x, int y) { setX(x); setY(y); } void Point2D::setX(int x) { this->x = x; cout « “Im from Point2D” « endl; } Point2D Point2D::operator+(Point2D o) { Point2D tmp;

tmp.setX(this->getX() + o.getX());
tmp.setY(this->getY() + o.getY());

return tmp; } ```

Comments