(C++ : Template) 함수 템플릿 호출시 주의사항

Posted by : at

Category : Cpp


#include <iostream>
using namespace std;

class Point
{
  int x, y;
public:
  Point(int a = 0, int b = 0) : x(a), y(b) {}
};

int main()
{
  Point p1(1, 2);
  
  cout << p1 << endl;   // 요걸 쓰고 싶다
}
#include <iostream>
using namespace std;

class Point
{
  int x, y;
public:
  Point(int a = 0, int b = 0) : x(a), y(b) {}
  
  friend ostream& operator<<(ostream& os, const Point& p);
};

ostream& operator<<(ostream& os, const Point& p)
{
  return os << p.x << ", " << p.y;
}

만약 Point가 template이라면??

#include <iostream>
using namespace std;

template<typename T>
class Point
{
  T x, y;
public:
  Point(T a = 0, T b = 0) : x(a), y(b) {}
  
  friend ostream& operator<<(ostream& os, const Point<T>& p);
};

template<typename T>
ostream& operator<<(ostream& os, const Point<T>& p)
{
  return os << p.x << ", " << p.y;
}

int main()
{
  Point<int> p1(1, 2);
  
  cout << p1 << endl;   // error! ???
}

왜 에러가 나지?

#include <iostream>
using namespace std;

template<typename T> void foo(T a)
{
  cout << "T" << endl;
}

void foo(int a)
{
  cout << "int" << endl;
}

int main()
{
  foo(3);   // 'int' 출력 됨 -> 정확한 타입이 우선된다.
}
#include <iostream>
using namespace std;

template<typename T> void foo(T a)
{
  cout << "T" << endl;
}

void foo(int a);    // 구현부를 지워 둠.

int main()
{
  foo(3);   // error - 정확한 선언의 구현부가 없기에 링크에러 발생
}
#include <iostream>
using namespace std;

template<typename T> class Point{};

template<typename T> void foo(Point<T> a)
{
  cout << "T" << endl;
}

void foo(Point<int> a) { cout << "int" << endl; }

int main()
{
  Point<int> p;
  foo(3);   // int - 역시 정확한 버전을 사용함.
}

다시 문제로 돌아가 보자.

#include <iostream>
using namespace std;

template<typename T>
class Point
{
  T x, y;
public:
  Point(T a = 0, T b = 0) : x(a), y(b) {}
  
  friend ostream& operator<<(ostream& os, const Point<T>& p);
};

// 함수 템플릿
template<typename T>
ostream& operator<<(ostream& os, const Point<T>& p)
{
  return os << p.x << ", " << p.y;
}

int main()
{
  Point<int> p1(1, 2);  // 여기가 호출 되는 순간 Point<int>를 생성하게 된다.
  
  cout << p1 << endl;   // error! ???
}
// T : int이기에
class Point<int>
{
  int x, y;
public:
  Point(int a = 0, int b = 0) : x(a), y(b) {}
  
  friend ostream& operator<<(ostream& os, const Point<int>& p);
  // 이렇게 된 순간 operator<<는 Point<int>로 확정이 되어 버린다.
  // friend ostream& operator<<(ostream& os, const Point<int>& p);
  // 를 찾을수 없기에 에러가 발생하는 것.
};

해결법?

#include <iostream>
using namespace std;

template<typename T>
class Point
{
  T x, y;
public:
  Point(T a = 0, T b = 0) : x(a), y(b) {}
  
  // friend ostream& operator<<(ostream& os, const Point<T>& p);
  // 함수 템플릿을 friend로 선언함으로 해결가능.
  template<typename U>
  friend ostream& operator<<(ostream& os, const Point<U>& p)
};

// 함수 템플릿
template<typename T>
ostream& operator<<(ostream& os, const Point<T>& p)
{
  return os << p.x << ", " << p.y;
}

int main()
{
  Point<int> p1(1, 2);  // 여기가 호출 되는 순간 Point<int>를 생성하게 된다.
  
  cout << p1 << endl;
}

하지만 더 좋은 방법이 있다.

#include <iostream>
using namespace std;

template<typename T>
class Point
{
  T x, y;
public:
  Point(T a = 0, T b = 0) : x(a), y(b) {}
  
  // friend ostream& operator<<(ostream& os, const Point<T>& p);
  // 구현을 클래스 내부에 한다.
  friend ostream& operator<<(ostream& os, const Point<T>& p)
  {
    return os << p.x << ", " << p.y;
  }
};

// 함수 템플릿
template<typename T>
ostream& operator<<(ostream& os, const Point<T>& p)

int main()
{
  Point<int> p1(1, 2);  // 여기가 호출 되는 순간 Point<int>를 생성하게 된다.
  
  cout << p1 << endl;
}

About Taehyung Kim

안녕하세요? 8년차 현업 C++ 개발자 김태형이라고 합니다. 😁 C/C++을 사랑하며 다양한 사람과의 협업을 즐깁니다. ☕ 꾸준한 자기개발을 미덕이라 생각하며 노력중이며, 제가 얻은 지식을 홈페이지에 정리 중입니다. 좀 더 상세한 제 이력서 혹은 Private 프로젝트 접근 권한을 원하신다면 메일주세요. 😎

Star
Useful Links