C ++では、変数の型をどのように見つけるのですか?
C ++では、変数の型をどのように見つけるのですか?
回答:
typeid演算子を使用できます。
#include <typeinfo>
...
cout << typeid(variable).name() << endl;
i
コンパイラの整数を意味します。返される名前は規格では指定されていません。
typeid
は非常に省略されており、コンパイラ固有のものであり、人間が使用するためのものではありません。それらを「デマングル」することができます(実際の用語です)。gcc.gnu.org/ onlinedocs / libstdc ++ / manual / ext_demangling.htmlなどのコードを使用するか、などのコマンドラインユーティリティをc++filt
使用するか、さまざまなオンラインデマングラを使用してdemangler.comなど。
C ++とJavaScriptの主な違いは、C ++は静的型付き言語であり、Javascriptは動的型であることです。
動的型付き言語では、変数には何でも含めることができ、その型は瞬間的に保持する値によって指定されます。静的型付き言語では、変数の型が宣言されており、変更できません。
動的ディスパッチとオブジェクト構成およびサブタイピング(継承と仮想関数)だけでなく、静的ディスパッチとスーパータイピング(テンプレートCRTPを使用)も可能ですが、いずれの場合でも、変数のタイプはコンパイラーに認識されている必要があります。
言語が動的型システムであるので何かを設計したことが原因です。
それがあなたのデザインを再考したほうがいい場合は、それはあなたが使っている言語にとって自然ではない土地に入るので(キャタピラで高速道路に行くか、車で水に行くようなものです)
通常、C ++で変数の型を検索するのは間違った質問です。これは、CやPascalなどの手続き型言語で使用する傾向があります。
タイプに応じて異なる動作をコーディングする場合は、関数のオーバーロードやオブジェクトの継承などについて学習してください。これは、C ++の初日にはすぐには意味がありませんが、そのままにしておいてください。
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
}
typeid
単に静的なコンパイル時チェックにすることはできません-定義により-これは最適化を促進しません。For a template function, I need to special case the code based on the template variable
そうです、本当に欲しいのはCRTPイディオムによる静的なポリモーフィズムです。これはまさにそれが達成することです。
私の答えが役立つかどうかはわかりません。
簡単に言えば、実際に使用するために変数の型を知る必要はありません。
静的変数に型を指定する必要がある場合は、単純に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);
}
それはまだ少し面倒ですが、型なし言語に到達することができるのと同じくらい近いです。テンプレート変数を参照するときは常に、必ずテンプレート仕様をそこに置いてください。
たとえば、クラスと既知のタイプを比較する必要がある場合:
class Example{};
...
Example eg = Example();
次の比較行を使用できます。
bool isType = string( typeid(eg).name() ).find("Example") != string::npos;
typeid
名前をチェックする文字列型が含まれていることを確認します(typeid名には他のマングルデータがあるため、のs1.find(s2)
代わりにを実行するのが最善です==
)。
あなたは間違いなくのために行くことができ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番目の両方が機能する場合に注意してください。
std::cout << "I'm a variable of type " << typeid(n).name()
ます。(アーティファクトを防ぐために言い換えられましたが、別のチェックで修正できます)。あなたは絶対に比較をしたい場合でも、その後、それはやってそんなに良いでしょうtypeid(n) == typeid(int)