typeid
operator
타입의 정보를 조회합니다.
dynamic type 을 알아야 하는 경우와 polymorphic object 의 정적 타입 식별을 위해 사용됩니다.
목차 |
구문
typeid (
type
)
|
(1) | ||||||||
typeid (
expression
)
|
(2) | ||||||||
typeid 표현식은 lvalue 표현식 으로서, 정적 저장 기간 을 가지며, 다형적 타입 std::type_info 또는 이로부터 파생된 어떤 타입의 const 한정 버전인 객체를 참조합니다.
표준 라이브러리의 std::type_info 정의가 typeid 사용 시 보이지 않으면, 프로그램은 형식이 잘못되었습니다.
설명
만약 type 또는 expression 의 타입이 클래스 타입이거나 클래스 타입에 대한 참조인 경우, 해당 클래스 타입은 incomplete type 일 수 없습니다.
- 만약 expression 이 lvalue (C++11 이전) glvalue (C++11 이후) 이면서 다형성 타입의 객체 (즉, 하나 이상의 가상 함수 를 선언하거나 상속하는 클래스)를 식별하는 경우, typeid 표현식은 해당 표현식을 평가한 후 표현식의 동적 타입을 나타내는 std::type_info 객체를 참조합니다.
-
- 만약 expression 이 간접 참조 표현식 이고 피연산자가 널 포인터 값 으로 평가되는 경우, std::bad_typeid 타입의 핸들러와 일치하는 타입의 예외가 발생합니다 [1] .
- 그렇지 않은 경우, typeid 는 표현식을 평가하지 않으며 , 이 식별자가 나타내는 std::type_info 객체는 표현식의 정적 타입을 나타냅니다. Lvalue-to-rvalue, array-to-pointer, 또는 function-to-pointer 변환이 수행되지 않습니다.
|
(C++17 이후) |
만약 type 또는 expression 의 타입이 cv-qualified인 경우, typeid 의 결과는 cv-unqualified 타입을 나타내는 std::type_info 객체를 참조합니다 (즉, typeid ( const T ) == typeid ( T ) ).
만약 typeid 가 생성 중이거나 소멸 중인 객체(소멸자나 생성자 내부, 생성자의 initializer list 또는 default member initializers 에서)에 사용되면, 이 typeid 가 참조하는 std::type_info 객체는 가장 파생된 클래스가 아닌 경우에도 현재 생성 중이거나 소멸 중인 클래스를 나타냅니다.
- ↑ 다른 상황에서, 이러한 expression 을 평가하는 것은 정의되지 않은 동작을 초래합니다.
참고 사항
다형성 타입의 표현식에 적용될 때, typeid 표현식의 평가는 런타임 오버헤드(가상 테이블 조회)를 수반할 수 있으며, 그렇지 않은 경우 typeid 표현식은 컴파일 타임에 해결됩니다.
typeid 가 참조하는 객체의 소멸자가 프로그램 종료 시점에 실행되는지 여부는 명시되어 있지 않습니다.
동일한 타입에 대한 typeid 표현식의 모든 평가가 동일한
std::type_info
객체를 참조한다는 보장은 없지만, 이들은 동등하게 비교될 것이며,
이러한
type_info
객체들의
std::type_info::hash_code
는 동일할 것이며, 그들의
std::type_index
도 마찬가지일 것입니다.
const std::type_info& ti1 = typeid(A); const std::type_info& ti2 = typeid(A); assert(&ti1 == &ti2); // 보장되지 않음 assert(ti1 == ti2); // 보장됨 assert(ti1.hash_code() == ti2.hash_code()); // 보장됨 assert(std::type_index(ti1) == std::type_index(ti2)); // 보장됨
키워드
예제
이 예제는 type_info::name 이 전체 타입 이름을 반환하는 구현 중 하나를 사용한 출력을 보여줍니다; gcc나 유사한 컴파일러를 사용하는 경우 c++filt -t로 필터링하십시오.
#include <iostream> #include <string> #include <typeinfo> struct Base {}; // non-polymorphic struct Derived : Base {}; struct Base2 { virtual void foo() {} }; // polymorphic struct Derived2 : Base2 {}; int main() { int myint = 50; std::string mystr = "string"; double *mydoubleptr = nullptr; std::cout << "myint has type: " << typeid(myint).name() << '\n' << "mystr has type: " << typeid(mystr).name() << '\n' << "mydoubleptr has type: " << typeid(mydoubleptr).name() << '\n'; // std::cout << myint is a glvalue expression of polymorphic type; it is evaluated const std::type_info& r1 = typeid(std::cout << myint); // side-effect: prints 50 std::cout << '\n' << "std::cout<<myint has type : " << r1.name() << '\n'; // std::printf() is not a glvalue expression of polymorphic type; NOT evaluated const std::type_info& r2 = typeid(std::printf("%d\n", myint)); std::cout << "printf(\"%d\\n\",myint) has type : " << r2.name() << '\n'; // Non-polymorphic lvalue is a static type Derived d1; Base& b1 = d1; std::cout << "reference to non-polymorphic base: " << typeid(b1).name() << '\n'; Derived2 d2; Base2& b2 = d2; std::cout << "reference to polymorphic base: " << typeid(b2).name() << '\n'; try { // dereferencing a null pointer: okay for a non-polymorphic expression std::cout << "mydoubleptr points to " << typeid(*mydoubleptr).name() << '\n'; // dereferencing a null pointer: not okay for a polymorphic lvalue Derived2* bad_ptr = nullptr; std::cout << "bad_ptr points to... "; std::cout << typeid(*bad_ptr).name() << '\n'; } catch (const std::bad_typeid& e) { std::cout << " caught " << e.what() << '\n'; } }
가능한 출력:
======== output from Clang ========
myint has type: i
mystr has type: NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
mydoubleptr has type: Pd
50
std::cout<<myint has type : NSt3__113basic_ostreamIcNS_11char_traitsIcEEEE
printf("%d\n",myint) has type : i
reference to non-polymorphic base: 4Base
reference to polymorphic base: 8Derived2
mydoubleptr points to d
bad_ptr points to... caught std::bad_typeid
======== output from MSVC ========
myint has type: int
mystr has type: class std::basic_string<char,struct std::char_traits<char>,⮠
class std::allocator<char> >
mydoubleptr has type: double * __ptr64
50
std::cout<<myint has type : class std::basic_ostream<char,struct std::char_traits<char> >
printf("%d\n",myint) has type : int
reference to non-polymorphic base: struct Base
reference to polymorphic base: struct Derived2
mydoubleptr points to double
bad_ptr points to... caught Attempted a typeid of nullptr pointer!
결함 보고서
다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.
| DR | 적용 대상 | 게시된 동작 | 올바른 동작 |
|---|---|---|---|
| CWG 492 | C++98 |
typeid
가 cv-qualified 참조에 적용될 때,
결과가 참조된 타입을 나타냄 |
결과가 cv-unqualified 참조된 타입을
나타냄 |
| CWG 1416 | C++98 |
최상위 cv-qualification에 관한 문구가
오해될 수 있었음 |
문구를 개선함 |
| CWG 1431 | C++98 | typeid 가 std::bad_typeid 만 throw할 수 있었음 |
매치 가능한 파생 클래스들을
throw할 수 있도록 허용 |
| CWG 1954 | C++98 |
널 포인터 역참조가
expression
의 하위 표현식에서
검사될 수 있는지 불명확했음 |
최상위 레벨에서만 검사함 |
참고 항목
|
일부 타입의 정보를 포함하며, typeid 연산자가 반환하는 클래스
(class) |