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에서 떼어지는 것을 확인할 수 있었음