typeid演算子
型の情報を照会します。
ポリモーフィックオブジェクトの動的型が既知である必要があり、静的型識別に使用されます。
目次 |
[編集] 構文
typeid ( 型 ) |
(1) | ||||||||
typeid ( 式 ) |
(2) | ||||||||
typeid式は、静的記憶域期間を持ち、std::type_infoまたはそれから派生した型をconst修飾したバージョンのオブジェクトを参照する左辺値式です。
typeidを使用する際に、std::type_infoの標準ライブラリ定義が見えない場合、プログラムは不正です。
[編集] 説明
型または式の型がクラス型またはクラス型への参照である場合、そのクラス型は不完全型であってはなりません。
- 式がポリモーフィック型(つまり、少なくとも1つの仮想関数を宣言または継承するクラス)のオブジェクトを識別する左辺値(C++11まで)glvalue(C++11以降)式である場合、typeid式は式を評価し、式の動的型を表すstd::type_infoオブジェクトを参照します。
- 式が間接参照式であり、そのオペランドがヌルポインタ値に評価される場合、std::bad_typeid型のハンドラに一致する型の例外がスローされます[1]。
- それ以外の場合、typeidは式を評価せず、識別するstd::type_infoオブジェクトは式の静的型を表します。左辺値から右辺値への変換、配列からポインタへの変換、または関数からポインタへの変換は実行されません。
|
(C++17以降) |
型または式の型がcv修飾されている場合、typeidの結果はcv非修飾型を表すstd::type_infoオブジェクトを参照します(つまり、typeid(const T) == typeid(T))。
オブジェクトが構築中または破棄中(デストラクタ内、またはコンストラクタ内(コンストラクタの初期化リストまたはデフォルトメンバ初期化子を含む))にtypeidが使用された場合、このtypeidによって参照されるstd::type_infoオブジェクトは、それが最も派生したクラスでなくても、構築中または破棄中のクラスを表します。
- ↑ 他のコンテキストでは、そのような式の評価は未定義動作になります。
[編集] 備考
ポリモーフィック型の式に適用された場合、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); // not guaranteed assert(ti1 == ti2); // guaranteed assert(ti1.hash_code() == ti2.hash_code()); // guaranteed assert(std::type_index(ti1) == std::type_index(ti2)); // guaranteed
[編集] キーワード
[編集] 例
type_info::nameが完全な型名を返す実装の1つを使用した出力例。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修飾された参照に適用された場合 型の場合、結果は参照された型を表します |
結果は cv非修飾参照型を表します |
| CWG 1416 | C++98 | トップレベルに関する記述 cv修飾は誤解される可能性があります |
記述を改善しました |
| CWG 1431 | C++98 | typeidはstd::bad_typeidをスローすることのみが許可されていました | スローすることが許可されています 一致する派生クラス |
| CWG 1954 | C++98 | ヌルポインタのデリファレンスが不明でした 式のサブ式でチェックできます |
トップレベルでのみチェックされます |
[編集] 関連項目
| ある型の情報を保持し、typeid演算子によって返されるクラス (クラス) |