본 글은 코드누리의 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?
- 동일한 인자를 받는다면 함수 템플릿보다 일반 함수가 우선해서 선택됨
- 함수 템플릿이 있고, 인자로 넘어가는 템플릿의 타입을 직접 받는 일반 함수의 선언만 있다면 링크 에러
- 아무리 템플릿 버전이 있다고 해도 정확한 타입의 인자를 받는 함수가 있다면 그 함수로 간다.
- 템플릿 안에 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 |
댓글