클래스 템플릿에 선언된 friend 함수를 외부에 정의하는 방법

2022. 3. 21. 09:26C++

template <typename T>
class Stack
{
    ...
    
public:
    friend std::ostream& operator<<(ostream&, Stack<T> const&);     
}

// ERROR!!
template <typename T>
std::ostream& operator<<(ostream&, Stack<T> const&)
{
    ...
}

클래스 템플릿 안에 출력을 위한 operator<< 함수가 선언되어 있다고 가정했을 때, 위와 같이 클래스 외부에 정의하면 정의를 찾을 수 없다는 링크 에러가 발생한다. 클래스 내부에 선언된 operator<< 함수는 non-template 함수이고, 외부에 정의된 것은 단순히 함수 템플릿이기 때문에 둘은 관련이 없다. 

 

  • 다른 템플릿 파라미터 사용
template <typename T>
class Stack
{
    ...
    
public:
    template <typename U>
    friend std::ostream& operator<<(ostream&, Stack<U> const&);     
}

template <typename U>
std::ostream& operator<<(ostream&, Stack<U> const&)
{
    ...
}

 

  • 전방 선언 및 특수화
template <typename T>
class Stack;
template <typename T>
std::ostream& operator<<(ostream&, Stack<T> const&);

template <typename T>
class Stack
{
    ...
    
public:
    friend std::ostream& operator<< <T>(ostream&, Stack<T> const&);     
}

template <typename T>
std::ostream& operator<<(ostream&, Stack<T> const&)
{
    ...
}

이 방법에서 operator<< <T>(...)와 같이 특수화를 시켜서 클래스 내부에 non-template 함수를 선언한게 아닌 외부 함수 템플릿을 사용하도록 연결시켜 준 것을 알 수 있다.

 

[참고]

- C++ Templates: The Complete Guide, 2nd Edition