[Modern C++] 항목 4: 연역된 형식을 파악하는 방법을 알아두라

게시:     수정

카테고리:

태그: ,

이 글은 아래의 책을 정리하였습니다. 이펙티브 모던 C++, 스콧 마이어스 저자, 류광 번역

📦 1. 형식 연역

👉🏻 항목 4: 연역된 형식을 파악하는 방법을 알아두라

  • 연역된 형식을 파악하는 세 가지 시점
    1. 코드 작성/수정
    2. 컴파일 시점
    3. 실행 시점

1️⃣ 코드 작성/수정

const int theAnswer = 42;

auto x = theAnswer; // 형식 = int
auto y = &theAnswer; // 형식 = const int*
  • IDE 편집기를 사용한다.
    • 프로그램 개체에 마우스를 올려, 형식을 확인할 수 있다.
    • 코드의 상태가, 컴파일러가 코드를 파싱해서 형식 연역을 수행할 수 있는 수준이어야 한다.
    • 복잡한 형식이 관여할 때는, 도움이 되지 않을 수 있다.
  • 완전히 믿으면 안 된다.
    • 뒤에서 나올 std::type_info::name와 비슷하게 힌트로만 사용해야 한다.

2️⃣ 컴파일 시점

// TD(Type Displayer)를 선언만 해둠
template<typename T>
class TD;

TD<decltype(x)> xType;
TD<decltype(y)> yType;
// 출력
error: 'xType'은() 정의되지 않은 class 'TD<int>'을() 사용합니다.
error: 'yType'은() 정의되지 않은 class 'TD<const int *>'을() 사용합니다.
  • 오류를 의도적으로 발생시켜, 컴파일러의 진단 메시지를 확인한다.

3️⃣ 실행 시점

함수 사용

cout << typeid(x).name() << '\n';
cout << typeid(y).name() << '\n';
  • GNU, Clang 컴파일러는 특별한 방식으로 보고한다.
    • inti
    • const int*PKi (PK = pointer to konst)
  • Microsoft 컴파일러는 평범하게 보고한다.
template<typename T>
void f(const T& param) {
	cout << "T = " << typeid(T).name() << '\n';
	cout << "param = " << typeid(param).name() << '\n';
}

vector<Widget> createVec();

const auto vw = createVec();
if(!vw.empty()) {
	f(&vw[0]);
	...
}
// 출력 (Microsoft 컴파일러)
T = class Widget const *
param = class Widget const * // ⚠️ 틀림
  • paramclass const Widget * const &으로 나왔어야 했다.
    • 항목 1의 ParamType이 포인터/참조 형식이지만, 보편 참조는 아닌 경우에 해당
  • std::type_info::name는 믿을 만하지 않다.
    • 템플릿 함수에 값 전달 매개변수로 전달된 것처럼 취급한다.
    • const, volatile, 참조가 무시된다.

Boost 라이브러리 사용

#include <boost/type_index.hpp>

template<typename T>
void f(const T& param) {
	using boost::typeindex::type_id_with_cvr;
	
	cout << "T = " << type_id_with_cvr<T>().pretty_name() << '\n';
	cout << "param = " << type_id_with_cvr<decltype(param)>().pretty_name() << '\n';
}
// 출력 (Microsoft 컴파일러)
T = class Widget const *
param = class Widget const * const &
  • type_id_with_cvrconst, volatile, 참조보존한다.

🧐 정리

  • 컴파일러가 연역하는 형식을 IDE 편집기, 컴파일러 오류 메시지, Boost 라이브러리를 통해 파악할 수 있는 경우가 많다.
  • 일부 도구는 유용하지 않고 정확하지 않을 수도 있으므로, C++ 형식 연역 규칙을 이해해야 한다.

Cpp 카테고리 내 다른 글 보러가기

댓글남기기