본문 바로가기
C++/[ecourse] C++ Template

4. 템플릿 기본 문법 - 클래스 템플릿

by 헛둘이 2022. 9. 27.

본 글은 코드누리의 Template Programming 강좌를 개인 학습 목적으로 정리한 글 입니다.

https://www.ecourse.co.kr/course-status/

 

클래스 템플릿의 기본 모양
  • 멤버 함수에서 사용하는 클래스 템플릿 이름은 Complex<T> 대신 Complex라고 사용할 수 있다.
  • 템플릿 인자를 초기화할 때는 {} (일관된 초기화 기법)을 사용하면 됨
template<typename T>
class Point
{
	T x, y;
public:
	Point(T a = {}, T b = {})
		: x(a), y(b)
	{

	}
	
    Point getPoint() const
    {
    	return Point(x, y);
    }
};

 

템플릿 멤버 함수를 외부에 구현할 때
  • 외부에도 template<typename T>를 적어주어야 함
  • 그리고 템플릿 이름도 <T>를 붙여주어야 함.
  • 외부에서는 이게 템플릿인지 일반함수인지 모르기 때문
template<typename T>
T Complex<T>::getReal() const
{
	return T();
}

 

 

 

클래스 템플릿의 멤버함수 템플릿을 외부에 만들 때
  • 아래와 같이 클래스 타입 T와 멤버함수 타입 U를 각각 적어주어야 함
template<typename T>
template<typename U>
T Complex<T>::func(const U& c)
{
	return T();
}
  • 이런걸 언제 쓰느냐?
  • 다른 타입의 템플릿 클래스로 초기화할 때 복사 생성자에 사용한다.

 

template<typename T>
template<typename U>
Complex<T>::Complex(const Complex<U>& c)
{
}
  • 이렇게 만들면 Complex의 모든 타입에 대해 복사 생성 가능하다.
  • 일반화된 복사 생성자라고 불림
  • 그런데 이렇게 해서 빌드하면 private 멤버에 접근한다고 에러가 남
  • 이걸 해결하려면 아래와 같이 friend 관계로 만들어야 함
template<typename> friend class Complex;
  • 이 문구를 추가해주면 모든 타입의 Complex에 대해 friend 관계를 형성

 

 

 


템플릿과  friend 함수
  • Point 클래스의 출력을 위해 << 연산자 재정의를 하는 경우
  • Point의 멤버 변수에 접근하려면 friend를 사용해야 함
  • 그런데 friend로 만들어도 에러가 남 Why?

 

  1. 동일한 인자를 받는다면 함수 템플릿보다 일반 함수가 우선해서 선택됨
  2. 함수 템플릿이 있고, 인자로 넘어가는 템플릿의 타입을 직접 받는 일반 함수의 선언만 있다면 링크 에러
  3. 아무리 템플릿 버전이 있다고 해도 정확한 타입의 인자를 받는 함수가 있다면 그 함수로 간다.

 

  • 템플릿 안에 friend는 템플릿의 타입이 결정될 때 함수의 타입도 결정됨
  • 그래서 템플릿 안에 있는 friend는 T로 이미 타입이 결정되어 버려서 일반 함수로 취급됨
  • 그래서 그걸 찾는데 구현부가 없으므로 에러가 난 것임(바깥에 template 함수가 구현되어 있어도)
#include <iostream>
#include <boost/type_index.hpp>

using namespace std;
using namespace boost::typeindex;

template<typename T>
class Point
{
	T x, y;
public:
	Point(T a = {}, T b = {})
		: x(a), y(b)
	{}

	template<typename U>
	friend std::ostream& operator<< (std::ostream& os, const Point<U>& point);
};

int main()
{
	Point<double> dp;
	std::cout << dp << std::endl;
}

template<typename U>
std::ostream& operator<<(std::ostream& os, const Point<U>& point)
{
	return os << point.x << "," << point.y;
}

 

해결 방법은?
  • friend 함수 선언 시 friend 함수 자체를 template으로 선언
  • friend는 template<type..> 앞이 아니라 함수 시작부분에 앞에다 적어야 함
  • 그러나 위 버전의 단점은 모든 타입의 클래스와 friend라는 것
  • 구분하고 싶다면 그냥 클래스 안에 T타입 operator<<를 만든 후 선언부까지 집어넣어버리면 됨

'C++ > [ecourse] C++ Template' 카테고리의 다른 글

6. 템플릿 특수화  (1) 2022.09.29
5. 템플릿 기본 문법 - typename, template  (0) 2022.09.28
3. 배열과 템플릿  (0) 2022.09.26
2. Template Type Deduction  (0) 2022.09.26
1. Template Instantiation  (0) 2022.09.26

댓글