[EMC++] Item 4. 추론된 타입을 파악하는 방법을 알아둬라
Item 4. 추론된 타입을 파악하는 방법을 알아둬라
요즘 IDE들은 컴파일러가 타입을 어떻게 추론했는지 마우스만 갖다 대도 알려준다.
하지만 코드가 어느 정도 완성되어 있어야 컴파일러가 코드를 파싱해서 타입 추론을 할 수 있다.
그럼 IDE를 사용하는 방법 이외에 추론된 타입을 확인하는 3가지 방법에 대해 알아보자.
컴파일러의 진단을 이용하는 방법
위 방법은 알고 싶은 타입을 TD(정의 없는 클래스 템플릿)를 통해 인스턴스화 해보는 방법이다.
클래스 템플릿 하나를 정의 없이 선언만 해두고 이를 인스턴스화 하면 인스턴스화 할 템플릿 정의가 없어서 컴파일 오류가 발생한다. 해당 오류 메시지에 우리가 원하는 정보가 들어 있을 수 있다.
//타입을 확인하기 위한 템플릿 클래스.
template <typename T>
class TD;
int main() {
const int n = 10;
auto x = n;
auto y = &n;
TD<decltype(x)> xType;
TD<decltype(y)> yType;
return 0;
}
런타임 출력을 이용하는 방법
typeid
연산자를 이용해서 런타임에 특정 오브젝트의 타입을 출력할 수 있다.
const int n = 10;
auto x = n;
auto y = &n;
std::cout << typeid(x).name() << std::endl; // i
std::cout << typeid(y).name() << std::endl; // PKi (PK는 const를 가리키는 pointer를 의미)
하지만 typeid
는 reference-ness와 const-ness가 모두 무시된다는 문제가 있다.
int x = 27;
const int cx = x;
const int& rx = x;
std::cout << typeid(x).name() << std::endl; // int
std::cout << typeid(cx).name() << std::endl; // int
std::cout << typeid(rx).name() << std::endl; // int
template <typename T>
void f(const T& param) {
std::cout << typeid(T).name() << std::endl;
std::cout << typeid(param).name() << std::endl;
}
f(4);
// int
// int
typeid
를 사용하면 const
, volatile
이나 &
, &&
같은 참조 한정사가 모두 무시되어 정확한 타입을 추론하기 어렵다.
Boost.TypeIndex를 이용하는 방법
가장 정확하게 추론된 타입을 확인하는 방법은 boost 라이브러리를 사용하는 것이다.
Boost.TypeIndex
를 사용하면 런타임에도 정확한 타입 정보를 얻을 수 있다.
boost::typeindex::type_id_with_cvr
은 자신에게 전달된 argument의 const
, volatile
, 참조 한정사를 모두 보존한 오브젝트의 타입을 출력한다.
#include <boost/type_index.hpp>
using boost::typeindex::type_id_with_cvr;
int x = 27;
const int cx = x;
const int& rx = x;
std::cout << type_id_with_cvr<decltype(x)>().pretty_name() << std::endl; // int
std::cout << type_id_with_cvr<decltype(cx)>().pretty_name() << std::endl; // const int
std::cout << type_id_with_cvr<decltype(rx)>().pretty_name() << std::endl; // const int&
template <typename T>
void f(const T& param){
std::cout << type_id_with_cvr<T>().pretty_name() << std::endl;
std::cout << type_id_with_cvr<decltype(param)>().pretty_name() << std::endl;
}
f(4);
// int
// const int&
추론된 타입을 파악하는 방법을 알아두면 좋지만 타입 추론 규칙을 제대로 이해하는 것이 더욱 중요하다.