変数の型を取得するにはどうすればよいですか?


130

C ++では、変数の型をどのように見つけるのですか?



7
cout << typeid(variable).name()<< endl;
SRN

2
検索またはgoogleを使用してください:) stackoverflow.com/questions/81870/print-variable-type-in​​-c Theharshest is fast:D
Kariboo

14
@Kariboo、私はグーグルを使った、そしてそれは私をここに送った。
マイケルワーナー

この質問はそのままでは非常に不明確であり、さまざまな答えを見ても不明です。質問が受け入れられた答えを求めていることは決して明らかではありません。
Antti Haapala 2016

回答:


157

typeid演算子を使用できます。

#include <typeinfo>
...
cout << typeid(variable).name() << endl;

15
@David- iコンパイラの整数を意味します。返される名前は規格では指定されていません。
Bo Persson、2012

11
vector <int>で使用すると、St6vectorIiSaIiEEが返されます。WTF?
Boyan Kushlev、2016年

2
@bobbybrownあなただけじゃない!! google.co.uk/webhp#safe=off&q=St6vectorIiSaIiEE
リッチO'Kelly

5
によって返される名前typeidは非常に省略されており、コンパイラ固有のものであり、人間が使用するためのものではありません。それらを「デマングル」することができます(実際の用語です)。gcc.gnu.org/ onlinedocs / libstdc ++ / manual / ext_demangling.htmlなどのコードを使用するか、などのコマンドラインユーティリティをc++filt使用するか、さまざまなオンラインデマングラを使用してdemangler.comなど。
シンコデナダ

33

静的アサーションについてdecltypeは、特定のシナリオで非常に役立つC ++ 11が導入されました。


12

変数がある場合

int k;

あなたは使用してそのタイプを得ることができます

cout << typeid(k).name() << endl;

SOの次のスレッドを参照してください:同様の質問


9

C ++とJavaScriptの主な違いは、C ++は静的型付き言語であり、Javascriptは動的型であることです。

動的型付き言語では、変数には何でも含めることができ、その型は瞬間的に保持する値によって指定されます。静的型付き言語では、変数の型が宣言されており、変更できません。

動的ディスパッチとオブジェクト構成およびサブタイピング(継承と仮想関数)だけでなく、静的ディスパッチとスーパータイピング(テンプレートCRTPを使用)も可能ですが、いずれの場合でも、変数のタイプはコンパイラーに認識されている必要があります。

言語が動的型システムであるので何かを設計したことが原因です。

それがあなたのデザインを再考したほうがいい場合は、それはあなたが使っている言語にとって自然ではない土地に入るので(キャタピラで高速道路に行くか、車で水に行くようなものです)


C ++に動的な変更がある場合、それは素晴らしいものであり、typeofとparseInt、parseFloat関数も便利になると思いますが、たとえばC ++のメーカーがそれを難し​​くしている理由はわかりません!cout << "String"を書くのは良いことだと言う人
Waqas Tahir

決断は最高です!!!! #include <sstream> string str( "1912"); int strtointval; stringstream(str)>> strtointval;
Waqas Tahir 2015

@ワカスええと、何?それが最良であると言う人は言語を定義する人であり、IMOはそれと関係するあらゆることにおいてほぼ最終的な決定権を持っています。たとえば、優れたコーディング慣行です。そのコメントを言い換えて、もっと理にかなっていますか?
モニカの訴訟に資金を提供

まったくそう思わない。Java、C#、PHP、Perl、PythonなどはCおよびC ++で設計されており、キャタピラではありません。(「不明な」データベースから変数テーブルを開くデータベースアプリケーションを作成する場合、フィールドタイプを変数スキームに制御し、その逆を「非常に」動的な方法で制御する必要があります;))
TomeeNS

@TomeeNS:いいえ。それらは設計されていないCおよびC ++で書かれています。CやC ++自体が動的型を持たない場合でも、動的型を持っています。それは奇妙なことではありません。
エミリオガラヴァリア2017年

8

通常、C ++で変数の型を検索するのは間違った質問です。これは、CやPascalなどの手続き型言語で使用する傾向があります。

タイプに応じて異なる動作をコーディングする場合は、関数のオーバーロードオブジェクトの継承などについて学習してください。これは、C ++の初日にはすぐには意味がありませんが、そのままにしておいてください。


実際には、クラスObjectとサブクラスBookがあるとしましょう。たくさんのオブジェクトを格納できるボックスがあるとしましょう。しかし、何らかの理由でその中にすべてのブックをリストしたいとします。タイプをチェックする方がはるかにすっきりしており、メソッド「type」をObjectに追加してから、Bookでオーバーライドして「book」のようなものを返す必要があります
Paulo Cesar

他のルールと同様に、例外があります(そのため、私の「通常は」!)、コンテナは型理論を複雑にする傾向があります。私はこれまで、多形オブジェクトのコンテナーを好きではありませんでした。ほとんどの場合、テンプレート化された均一のコンテナータイプで十分で、よりクリーンです。
Pontus Gagge

テンプレートを使ってみませんか?
ブライアングレース

6

sizeid()を使用するのと同じように、typeid()を使用する有効なユースケースがあると思います。テンプレート関数では、テンプレート変数に基づくコードを特別なケースにする必要があるため、最大限の機能と柔軟性を提供します。

サポートされているタイプごとに関数のインスタンスを1つ作成する方が、ポリモーフィズムを使用するよりもはるかにコンパクトで保守が容易です。その場合でも、このトリックを使用して、関数の本体を1回だけ記述できます。

コードはテンプレートを使用しているため、以下のswitchステートメントは静的に1つのコードブロックのみに解決され、すべての誤ったケースであるAFAIKが最適化されます。

この例を考えてみましょう。ここで、Tがある型と別の型の場合に変換を処理する必要があるかもしれません。ハードウェアがmyClassAまたはmyClassBタイプのいずれかを使用するハードウェアにアクセスするために、クラスの特殊化に使用します。不一致の場合、データの変換に時間を費やす必要があります。

switch ((typeid(T)) {
  case typeid(myClassA):
    // handle that case
    break;
  case typeid(myClassB):
    // handle that case
    break;
  case typeid(uint32_t):
    // handle that case
    break;
  default:
    // handle that case
}

1
TypeId:Arduinoでtypeid()を使用できませんでした。また、typeid()はランタイムチェックであり、コンパイル時ではないため、最適化されたコードの生成には使用できません。
Dan Truong、2016年

1
ええ、いいえ、これはあなたが思ったようにはいきません。typeid単に静的なコンパイル時チェックにすることはできません-定義により-これは最適化を促進しません。For a template function, I need to special case the code based on the template variableそうです、本当に欲しいのはCRTPイディオムによる静的なポリモーフィズムです。これはまさにそれが達成することです。
underscore_d

4

私の答えが役立つかどうかはわかりません。

簡単に言えば、実際に使用するために変数の型を知る必要はありません。

静的変数に型を指定する必要がある場合は、単純にautoを使用できます。

クラスまたは構造体で "auto"を使用するより洗練されたケースでは、decltypeでテンプレートを使用することをお勧めします。

たとえば、他の誰かのライブラリを使用していて、「unknown_var」という変数があり、それをベクトルまたは構造体に配置したい場合は、次のようにできます。

template <typename T>
struct my_struct {
    int some_field;
    T my_data;
};
vector<decltype(unknown_var)> complex_vector;
vector<my_struct<decltype(unknown_var)> > simple_vector

お役に立てれば。

編集:良い尺度として、ここに私が考えることができる最も複雑なケースがあります:未知のタイプのグローバル変数を持つことです。この場合、c ++ 14とテンプレート変数が必要になります。

このようなもの:

template<typename T> vector<T> global_var;

void random_func (auto unknown_var) {
    global_var<decltype(unknown_var)>.push_back(unknown_var);
}

それはまだ少し面倒ですが、型なし言語に到達することができるのと同じくらい近いです。テンプレート変数を参照するときは常に、必ずテンプレート仕様をそこに置いてください。


2
#include <typeinfo>

...
string s = typeid(YourClass).name()

0

たとえば、クラスと既知のタイプを比較する必要がある場合:

class Example{};
...
Example eg = Example();

次の比較行を使用できます。

bool isType = string( typeid(eg).name() ).find("Example") != string::npos;

typeid名前をチェックする文字列型が含まれていることを確認します(typeid名には他のマングルデータがあるため、のs1.find(s2)代わりにを実行するのが最善です==)。


-2

あなたは間違いなくのために行くことができtypeid(x).name()、xは変数名です。実際には、データ型へのconst charポインターを返します。次のコードを見てください。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n = 36;
    char c = 'A';
    double d = 1.2;
    if(*(typeid(n).name()) == 'i'){
        cout << "I am an Integer variable" << endl;
    }
    if(*((char *) typeid(d).name()) == 'd'){
        cout << "I am a Double variable" << endl;
    }
    if(*((char *) typeid(c).name()) == 'c'){
        cout << "I am a Char variable" << endl;
    }
    return 0;
}

1番目と2番目の両方が機能する場合に注意してください。


最初の文字でタイプを認識することは非常に悪い考えです。
Dmitry Kuzminov

より具体的なドミトリーになっていただけますか?私はここであなたの要点を理解できませんでした。
ピカチュウ

これはに短縮できstd::cout << "I'm a variable of type " << typeid(n).name()ます。(アーティファクトを防ぐために言い換えられましたが、別のチェックで修正できます)。あなたは絶対に比較をしたい場合でも、その後、それはやってそんなに良いでしょうtypeid(n) == typeid(int)
ゾーイ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.