C++/[ecourse] C++ Template

2. Template Type Deduction

헛둘이 2022. 9. 26. 13:45

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

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

템플릿 타입 추론 방식

 

template<typename T>
void foo(const T a)
{

}
  • 여기서 T와 a의 타입이 서로 다를 수 있다.
  • int가 넘어오면 T는 int가 되고, a는 const int가 된다.

 

#include <iostream>
#include <boost/type_index.hpp>

using namespace std;
using namespace boost::typeindex;

template<typename T>
void foo(const T a)
{
	std::cout << "T: " << type_id_with_cvr<T>().pretty_name() << std::endl;
	std::cout << "a: " << type_id_with_cvr<decltype(a)>().pretty_name() << std::endl;
	std::cout << std::endl;
}

int main()
{
	foo(3);		// T는 int, a는 const int
	foo(3.3);
}

T: int
a: int const

T: double
a: double const

 

  • C++에서 제공하는 typeid() 함수를 통해 변수의 타입을 구할 수 있다.
  • 하지만 typeid()로는 const, reference, volatile과 같은 특성은 생략된다.
  • boost 라이브러리의 typeindex를 이용하면 const, reference, volatile의 속성까지 구할 수 있다.
  • 위 예제에서 보면 T는 int인데 a는 int const인 것을 확인할 수 있다.

 

 


타입 추론 규칙 1. 템플릿 인자(T)가 값 타입일 때(T a)

 

  • 함수 인자가 가진 const, volatile, reference 속성을 제거하고 T의 타입 결정
  • 주의할 것은 인자가 가진 const만 제거됨
  • const char*의 경우 따라가면 const이므로 이건 제거되지 않음
  • const char* const일 경우 포인터 자체에 붙은 const만 제거돼서 const char*가 됨

 

#include <iostream>
#include <boost/type_index.hpp>

using namespace std;
using namespace boost::typeindex;

template<typename T>
void foo(T a)
{
	std::cout << "T: " << type_id_with_cvr<T>().pretty_name() << std::endl;
	std::cout << "a: " << type_id_with_cvr<decltype(a)>().pretty_name() << std::endl;
	std::cout << std::endl;
}

int main()
{
	int n = 0;
	int& r = n;
	const int c = n; 
	const int& cr = c;

	foo(n);	//int
	foo(c);	//int
	foo(r); //int
	foo(cr);//int
}

T: int
a: int

T: int
a: int

T: int
a: int

T: int
a: int

 

 

템플릿 인자 T가 값일 때
넘어온 인자(메인 함수쪽) T (템플릿 T) a (함수인자)
int int int
const int int int
int & int  int
const int & int int
  • foo 함수에서 T a로 받으니 const와 reference가 전부 떨어진 것을 확인할 수 있었다.

 


타입 추론 규칙 2. 템플릿 인자(T)가 참조 타입일 때(T& a)
  • T&는 원본을 가리키게 되는 것
  • 함수 인자가 가진 reference 속성만 제거하고 T의 타입을 결정함
  • 단, 템플릿 인자가 const T&일 경우 함수 인자가 가진 const마저 제거하고 T 결정함
#include <iostream>
#include <boost/type_index.hpp>

using namespace std;
using namespace boost::typeindex;

template<typename T>
void foo(T& a)
{
	std::cout << "T: " << type_id_with_cvr<T>().pretty_name() << std::endl;
	std::cout << "a: " << type_id_with_cvr<decltype(a)>().pretty_name() << std::endl;
	std::cout << std::endl;
}

int main()
{
	int n = 0;
	int& r = n;
	const int c = n;
	const int& cr = c;

	foo(n);	//int
	foo(c);	//int
	foo(r); //int
	foo(cr);//int
}

 

T: int
a: int & __ptr64

T: int const
a: int const & __ptr64

T: int
a: int & __ptr64

T: int const
a: int const & __ptr64

 

템플릿 인자 T가 참조일 때
넘어온 인자(메인 함수쪽) T (템플릿 T) a (함수인자)
int int int &
const int const int const int &
int & int  int &
const int & const int const int &
  • T의 경우 타입의 reference가 전부 제거되었고 실제 함수 인자 a에서는 T'&' a의 &가 붙어서 표기됨

 

 

템플릿 인자(T)가 const 참조 타입일 때 (const T& )
#include <iostream>
#include <boost/type_index.hpp>

using namespace std;
using namespace boost::typeindex;

template<typename T>
void foo(const T& a)
{
	std::cout << "T: " << type_id_with_cvr<T>().pretty_name() << std::endl;
	std::cout << "a: " << type_id_with_cvr<decltype(a)>().pretty_name() << std::endl;
	std::cout << std::endl;
}

int main()
{
	int n = 0;
	int& r = n;
	const int c = n;
	const int& cr = c;

	foo(n);	//int
	foo(c);	//int
	foo(r); //int
	foo(cr);//int
}

T: int
a: int const & __ptr64

T: int
a: int const & __ptr64

T: int
a: int const & __ptr64

T: int
a: int const & __ptr64

 

템플릿 인자 T가 const 참조일 때
넘어온 인자(메인 함수쪽) T (템플릿 T) a (함수인자)
int int const int &
const int int const int &
int & int  iconst nt &
const int & int const int &
  • 넘어온 인자 쪽의 const마저 T에서 떼어지는 것을 확인할 수 있었음