IDE 에디터
const int theAnswer = 10; auto x = theAnswer; auto y = &theAnswer;IDE 에디터(Visual Studio 등)는 변수에 마우스를 올리면 x는 int로, y는 const int*로 추론되었다는 것을 보여줄 것이다.
이렇게 작동하게 하기 위해서 IDE는 내부적으로 C++ 컴파일러를 동작시킨다. 만약 이 컴파일러가 타입을 추론하기에 부족한 상태라면 추론된 타입을 보여줄 수 없다. 따라서, int 같은 단순한 형태라면 문제가 없지만 더 호환성 있는 타입이 사용된다면 IDE에 표시되는 정보는 유용하지 않을 수 있다.
컴파일러 진단
컴파일러를 사용하여 타입을 추론하는 효과적인 방법은 추론된 타입을 컴파일 에러가 나도록 사용하는 것이다. 이렇게 하면 에러 메세지를 통해 추론된 변수의 타입을 확인할 수 있다.
예를 들면, 먼저 아래와 같은 형태의 정의되지 않은 템플릿을 만들 수 있다.
template<typename T> class TD;그리고 이러한 템플릿을 인스턴스화 하는 것은 에러 메시지를 발생시킬 것이다. 위의 예제에서의 x와 y의 타입을 알고 싶다면 아래와 같이 사용할 수 있다.
TD<decltype(x)> xType; TD<decltype(y)> yType;
런타임 결과
실행 화면에서 표시될 수 있는 텍스트의 형태로 타입을 출력하기 위해서 아래와 같은 방법을 사용할 수 있다.
std::cout << typeid(x).name() << '\n'; std:;cout << typeid(y).name() << '\n';컴파일러마다 표시되는 문자가 다를 수 는 있지만 마이크로소프트의 컴파일러는 정확한 결과를 보여준다. 하지만 그렇다고 문제가 해결된 것은 아니다. 조금 더 복잡한 경우를 살펴보자.
template<typename T> void f(const T& param); std::vector<Widget> createVec(); const auto vw = createVec(); if(!vm.empty()) { f(&vm[0]); ... }위 코드에 typeid를 확인하기 위해서 f 함수를 아래와 같이 정의한다.
template컴파일 결과는 마이크로소프트 컴파일러의 경우 둘 다 class Widget const * 로 표시된다.void f(const T& param) { using std::cout; cout << "T = " << typeid(T).name() << '\n'; cout << "param = " << typeid(param).name() << '\n'; ...
하지만 소스에서 param 의 타입은 const T&로, T와는 다르다. 이처럼 std::type_info::name 은 항상 신뢰할 수 는 없다.
그 이유는 std::type_info::name의 특성 상 템플릿 함수를 by-value 파라미터로 받는다는데 있다. 만약 타입이 레퍼런스이면, 그 레퍼런스의 특징이 삭제(무시)되고, 삭제된 레퍼런스가 const라면 그 또한 삭제된다. 따라서 const Widget * const & 가 const Widget * 이 된 것이다.
이러한 현상은 IDE에서도 동일하게 일어난다. 해결방법 중 하나는 Boost TypeIndex 라이브러리를 사용하는 것이다. Boost를 사용하면 다음과 같이 표현할 수 있다.
#include이것이 작동하는 방법은 boost::typeindex::type_id_with_cvr 이 우리가 알고자 하는 변수를 인자로 받아서 const와 volatile, 혹은 & 성질을 지우지 않고 이용하는 것이다. .pretty_name()은 인자의 속성을 std::string으로 반환해준다.template void f(const T& param) { using std::cout; using boost::typeindex::type_id_with_cvr; //show T cout << "T = " << type_id_with_cvr ().pretty_name() << '\n'; //show param's type cout << "param = " << type_id_with_cvr ().pretty_name() << '\n'; ... }
이 같은 방법을 사용하면 T의 타입은 Widget const* 로, param의 타입은 Widget const* const&로 정확하게 알 수 있다.
댓글 없음:
댓글 쓰기