스토리텔링 개발자

[Effective Modern C++] 4. 추론 타입 파악하기 본문

개발/Effective Modern C++

[Effective Modern C++] 4. 추론 타입 파악하기

김디트 2025. 2. 10. 11:14
728x90

항목 4. 추론된 타입을 파악하는 방법을 알아두라

 

 

 

추론 타입 확인 방법 세 가지
  • 코드를 작성, 수정하는 시점(IDE 편집기)
  • 컴파일 시점(컴파일 에러를 통한 확인)
  • 런타임 시점(코드 삽입을 통한 타입 정보 출력)

 

 

 

IDE 편집기
  • 프로그램 개체(변수, 매개변수, 함수 등) 위에 마우스 커서를 올리면 그 개체의 타입을 표시해 주는 것이 많다.
  • IDE 안에서 C++ 컴파일러(혹은 컴파일러의 front가) 실행되기 때문에 가능한 것.
    • 그러므로 코드가 컴파일 될 수 있는 상태여야 한다.
  • 복잡한 타입의 경우 그리 도움이 되지 않을 수 있다.

 

 

 

컴파일러 에러 메시지
  • 일부러 문제를 발생시킨다면, 에러 메시지에는 그 문제를 일으킨 타입이 언급된다.
// TD를 선언만 해둔다. TD는 "Type Dispalyer(형식 표시기)"를 뜻한다.
template<typename T>
class TD;

// 아래처럼 하면, 각각의 타입이 에러로 출력된다.
TD<decltype(x)> xType;
TD<decltype(y)> yType;

 

 

 

실행시점 출력
  • printf를 이용한다.
  • 까다로운 점은, 원하는 타입으로부터 표시에 적합한 형태의 텍스트를 만들어 내는 것이다.
  • typeid와 std::type_info::name을 사용하면 될까?
std::cout << typeid(x).name() << '\n';
std::cout << typeid(y).name() << '\n';
  • 위 코드가 하고 있는 가정
    • 각 객체가 typeid를 적용하면 std::type_info 타입의 객체가 산출되고,
    • 그 std::type_info 객체에는 name이라는 멤버 함수가 있으며,
    • 그 멤버 함수는 타입의 이름을 나타내는 C 스타일 문자열(const char*)일 것이다.
  • 표준에 따르면 std::type_info::name이 의미 있는 뭔가를 돌려준다는 보장이 없다.
    • 하지만 대체로 컴파일러들은 개발자에게 도움을 주려고 노력한다.
  • 문제 1. std::type_info::name이 출력하는 정보의 표현 방법이 일관성이 없다.
  • 문제 2. std::type_info::name은 믿을만하지 않다.
template<typename T>
void f(const T& param)
{
    using std::cout;
    cout << "T =     " << typeid[T].name() << '\n';
    cout << "param = " << typeid[param].name() << '\n';
}

std::vector<Widget> createVec();

const auto vw = createVec();

if(!vw.empty())
{
    f(&vw[0]);
    ...
}

// GNU 컴파일러
// PK는 Pointer to Konst(const)를 뜻한다.
// T =     PK6Widget(즉, const Widget*를 뜻한다)
// param = PK6Widget

// MS 컴파일러
// T =     class Widget const *
// param = class Widget const *
  • T와 param의 타입이 같다?
    • param의 선언된 타입은 const T& 이므로
    • param의 타입은 const Widget * const& 여야 한다.
    • 하지만 틀린 타입을 출력한다.
  • 이는 std::type_info::name은 반드시 주어진 타입을 템플릿 함수에 값 전달 매개변수로 전달된 것처럼 취급해야 한다는 표준을 준수했기 때문이다.
    • 그래서 param의 타입에서 참조 제거, 상수성 제거(항목 1 참조)가 되어 const Widget*이 된 것이다.
  • 마찬가지로 IDE 편집기가 표시하는 타입 정보 역시 불확실한 경우가 많다.

 

 

 

Boost TypeIndex 라이브러리(Boost.TypeIndex)
  • 이는 반드시 성공하게 설계되어 있다.
  • 표준은 아니지만, IDE나 TD 같은 템플릿도 표준이 아닌 건 똑같다.
#include <boost/type_index.hpp>

template<typename T>
void f(const T& param)
{
    using std::cout;
    using boost:typeindex::type_id_with_cvr;
    
    // T를 표시
    cout << "T =     "
         << type_id_with_cvr<T>().pretty_name()
         << '\n';
    // param의 타입을 표시
    cout << "param = "
         << type_id_with_cvr<decltype(param)>().pretty_name()
         << '\n';
 }
728x90
Comments