typeidのname()

zxc
記事: 79
登録日時: 13年前
住所: 日本の背骨(?)あたり

typeidのname()

投稿記事 by zxc » 12年前

  型によって処理を変えるようなことをするなら、オーバーロードかTypeidを使うのかな? 他にも方法があるかもしれない。とりあえずname関数はどんな文字列返すのか。よく知らないけどname関数はtypeidのものじゃないらしいね・・・
  型を示すものとまったく同じ文字列  

CODE:


#include
#include


class A{public :virtual ~A(){}};
class B:public A{};

int main(){
	using namespace std;

	A a;
	B** bpp;
	B barray[10];
	B b;
	A* ap1 = &b;
	A* ap2 = &a;

	cout 
int
short
double
__int64
char
unsigned int
float
class A
class A
class B *
class B * *
class B [10]
typeid( ap1 ).name() = class A *
class B
typeid( ap2 ).name() = class A *
class A
続行するには何かキーを押してください . . .
  ・longとかshortは特別
  ・派生クラスのアドレスをもつ、基底クラスのポインタ変数は「基底クラス*」、指しているのは「派生クラス」(基底クラスにvirtualのデストラクタがないとダメみたい)

  今更ながらこのコードタグは便利だなぁ・・・・

YuO
記事: 947
登録日時: 14年前

Re: typeidのname()

投稿記事 by YuO » 12年前

実は,std::typeinfo::nameは何を返すかについて,ほとんど決められていません。

ISO/IEC 14882:2011 18.7.1 Class type_info

CODE:

const char* name() const noexcept;
9 Returns: An implementation-defined NTBS.
NTBSはA null-terminated byte string (17.5.2.1.4.1 Byte strings)で,Cのいわゆる「文字列」です。

上記より,nameは型によらず同じ文字列や空文字列を返す実装も許されます。
なので,あまりnameに期待しない方がよいかと思います。

アバター
みけCAT
記事: 6734
登録日時: 14年前

Re: typeidのname()

投稿記事 by みけCAT » 12年前

zxc さんが書きました:・longとかshortは特別
どう特別だとお考えですか?
そもそも実験にlongが入っていないですし、shortもintやdoubleとかと同じように型名がそのまま表示されていて、特別には見えません。

zxc
記事: 79
登録日時: 13年前
住所: 日本の背骨(?)あたり

Re: typeidのname()

投稿記事 by zxc » 12年前

YuO さんが書きました:実は,std::typeinfo::nameは何を返すかについて,ほとんど決められていません。

ISO/IEC 14882:2011 18.7.1 Class type_info

CODE:

const char* name() const noexcept;
9 Returns: An implementation-defined NTBS.
NTBSはA null-terminated byte string (17.5.2.1.4.1 Byte strings)で,Cのいわゆる「文字列」です。

上記より,nameは型によらず同じ文字列や空文字列を返す実装も許されます。
なので,あまりnameに期待しない方がよいかと思います。
  型に特異の文字列を返すとは限らないので、あまり信用できないわけですか・・・
とするとなるべく使用しないですむものを考える方が良さそうですね。
みけCAT さんが書きました:
zxc さんが書きました:・longとかshortは特別
どう特別だとお考えですか?
そもそも実験にlongが入っていないですし、shortもintやdoubleとかと同じように型名がそのまま表示されていて、特別には見えません。
  自分の書き方は言葉足らずですね。ご指摘のとおり実験と説明に不備があります。ちなみにlongはそのままlongでした。結果のみから型名がよく分からないのは、long longのみです。 
  特別と言ったのは自分が、「int」を省略しているshortにunsigned同様「 int」と付け加えられた、省略していないものが返ってくることを期待していたからです。書いておかないとダメでしたね。unsignedのほうが変わっているのかもしれませんし。

アバター
みけCAT
記事: 6734
登録日時: 14年前

Re: typeidのname()

投稿記事 by みけCAT » 12年前

short intとかunsigned shortとかlong doubleなどを試そうとしたのですが、
全然違う結果が返ってきて参考になりませんでした…
C++4.7.2 http://ideone.com/NDuvoY
C++4.3.2 http://ideone.com/B7R4hB
C++11 http://ideone.com/WP9tYZ
C++ http://codepad.org/w6riupO9

ぼずお
記事: 1
登録日時: 13年前

Re: typeidのname()

投稿記事 by ぼずお » 12年前

私はtypenameはデバッグ確認用途のみに使っていますね。

メモリリーク時にどの型が漏れたか表示したり、
タスクを一覧を表示するときに型名を取ったり、です。
いずれもDebugビルドのときだけ。

typeinfoはせいぜい型の比較と名前の取得くらいしか使い道がないこと、
RTTIを有効に出来る環境でしか使えないことから
いまいち使えない印象です。
(ビルド設定によっては謎の型名文字列のメモリリークが起こったりしました。)
もしかしたら活用方法があるのかもしれませんが・・

dynamic_castは割と使います。
最後に編集したユーザー ぼずお on 2013年7月04日(木) 23:03 [ 編集 1 回目 ]

YuO
記事: 947
登録日時: 14年前

Re: typeidのname()

投稿記事 by YuO » 12年前

zxc さんが書きました:  自分の書き方は言葉足らずですね。ご指摘のとおり実験と説明に不備があります。ちなみにlongはそのままlongでした。結果のみから型名がよく分からないのは、long longのみです。 
long long型はlong型と別です。
で,VC++では歴史的な経緯により,__int64型の別名としてlong long型が存在します。
int型,short型,char型の別名として__int32型,__int16型,__int8型が存在するのとは異なります。
ref) __int8, __int16, __int32, __int64 (日本語版は訳しすぎがあるので英語版へリンク)
みけCAT さんが書きました:short intとかunsigned shortとかlong doubleなどを試そうとしたのですが、
全然違う結果が返ってきて参考になりませんでした…
こちらはgccの実装の場合ですね。
先に書いた通り,name()でどういう文字列が変えるかは実装依存なので,これでもかまわないわけです。

zxc
記事: 79
登録日時: 13年前
住所: 日本の背骨(?)あたり

RE: typeidのname()

投稿記事 by zxc » 12年前

みけCAT さんが書きました:short intとかunsigned shortとかlong doubleなどを試そうとしたのですが、
全然違う結果が返ってきて参考になりませんでした…
  ここまで違うとは思いませんでした。しかしYuOさんの仰るとおり、文字列には厳しい決まりが無いようなので、今回自分が実験で行ったようなことをせずに、比較によって型を限定するなら特に問題ない、むしろそのように使うべきなのだと今回のことで思いました。  
ぼずお さんが書きました:私はtypenameはデバッグ確認用途のみに使っていますね。

メモリリーク時にどの型が漏れたか表示したり、
タスクを一覧を表示するときに型名を取ったり、です。
いずれもDebugビルドのときだけ。

typeinfoはせいぜい型の比較と名前の取得くらいしか使い道がないこと、
RTTIを有効に出来る環境でしか使えないことから
いまいち使えない印象です。
(ビルド設定によっては謎の型名文字列のメモリリークが起こったりしました。)
もしかしたら活用方法があるのかもしれませんが・・

dynamic_castは割と使います。
  そのあたりの知識が無いのでよく分かりませんが、タスク一覧もメモリーリークも他の実装方法で、知りたいこと(この場合型)を明らかにすることはおそらく可能ですよね。typeinfo自体が、(型ユニークな文字列の比較による)実行時の型情報を利用したプログラムをサポートするもの、だと自分は思ってます。要するに実行時ではなく実行前に、型が決定されていることが明らかならば、使わないという選択肢もきっとあるでしょうし、広く使うクラスや大量のデータを動かすクラスならば、むしろ使うべきではないと思います。
  RTTIが使える環境でしか~という件も、それをサポートするためのものなので使えなくて当たり前。と自分は思ってますが違うんでしょうか。
  ただ、typeidの返り値で複雑な分岐構造をとって何か行うのならば、StatePatternなど別の方法もありますし、多くの場合それらに劣ることが多いらしいので、使い道があまり無い、使いどころを考える必要があるという考えには同意します。
YuO さんが書きました: long long型はlong型と別です。
で,VC++では歴史的な経緯により,__int64型の別名としてlong long型が存在します。
int型,short型,char型の別名として__int32型,__int16型,__int8型が存在するのとは異なります。
ref) __int8, __int16, __int32, __int64 (日本語版は訳しすぎがあるので英語版へリンク)
  そうらしいですね。似たようなものかと思っていたら経緯は異なるようです。仮に型名を出力するなら整形するクラス等を作るべきなんでしょうね。

  それよりも個人的に気になるのは
YuO さんが書きました:上記より,nameは型によらず同じ文字列や空文字列を返す実装も許されます。
  ここです。
  型によらないものを返す可能性があるなら、これらを信用し実行時の型情報を利用したプログラムを組むことは、あまり望ましいことではないように思えますが、そういうことではないのでしょうか。もしくはtypeidやname関数の実装として、返す文字列が型ユニークであることを保障しているわけではない、ということなのでしょうか。

YuO
記事: 947
登録日時: 14年前

Re: typeidのname()

投稿記事 by YuO » 12年前

zxc さんが書きました:  それよりも個人的に気になるのは
YuO さんが書きました:上記より,nameは型によらず同じ文字列や空文字列を返す実装も許されます。
  ここです。
  型によらないものを返す可能性があるなら、これらを信用し実行時の型情報を利用したプログラムを組むことは、あまり望ましいことではないように思えますが、そういうことではないのでしょうか。もしくはtypeidやname関数の実装として、返す文字列が型ユニークであることを保障しているわけではない、ということなのでしょうか。
typeidは型を同定できるstd::type_infoを返します。
このtype_info自体は実行時の型情報として利用できます。

std::type_info::name()は,型によって情報が異なることを規格は保証していません。
このため,type_info::name()を型情報として扱うことができるかは処理系に依存します。

ただし,type_info::name()の戻り値はimplementation-definedなので,実装には文書化する義務があります。
例えば,VC++であれば,type_info Classに,
The type_info::name member function returns a const char* to a null-terminated string representing the human-readable name of the type.
とありますし,GCCであれば,The GNU C++ Library / Part I. Introduction / Chapter 1. Statusに,
[18.5.1]/7 The return value of std::type_info::name() is the mangled type name (see the previous entry for more).
とあります。
これらの処理系であれば,type_info::name()を型情報として扱うことができるでしょう。

ただ,type_info::name()の比較は文字列になるため,type_infoを==や!=で比較した方が移植性もあり,速度も速いでしょう。
そういう意味では,type_info::name()を実行時の型情報として必要になることはないと思われます。
type_info::name()はぼずおさんが書かれているようにデバッグ時の表示目的と割り切った方がよいでしょう。
# 関数に入ったときの引数の型をデバッグ表示する,等。

zxc
記事: 79
登録日時: 13年前
住所: 日本の背骨(?)あたり

Re: typeidのname()

投稿記事 by zxc » 12年前

  なるほど。nameではなくtype_infoでは型が同定できることが保障されているわけですね。・・・・nameは無くても困りませんね。