Bagaimana cara mendapatkan tipe variabel?

130

Di C ++, bagaimana cara menemukan tipe variabel?

0x499602D2
sumber
7
cout << typeid (variabel) .name () << endl;
SRN
2
Gunakan pencarian atau google :) stackoverflow.com/questions/81870/print-variable-type-in-c Theharshest is fast: D
Kariboo
14
@Kariboo, saya menggunakan Google dan itu mengirim saya ke sini.
Michael Warner
Pertanyaan ini sangat tidak jelas, dan bahkan setelah melihat berbagai jawaban; sama sekali tidak jelas bahwa pertanyaan itu mencari jawaban yang diterima.
Antti Haapala

Jawaban:

158

Anda dapat menggunakan operator typeid :

#include <typeinfo>
...
cout << typeid(variable).name() << endl;
Rich O'Kelly
sumber
15
@David - iBerarti integer pada kompiler Anda. Nama yang dikembalikan tidak ditentukan oleh standar.
Bo Persson
11
Ketika saya menggunakannya pada vektor <int> ia mengembalikan St6vectorIiSaIiEE. WTF?
Boyan Kushlev
2
@BobbyBrown kamu tidak sendiri !! google.co.uk/webhp#safe=off&q=St6vectorIiSaIiEE
Rich O'Kelly
5
Nama yang dikembalikan oleh typeidsangat disingkat, khusus untuk kompiler, dan tidak dimaksudkan untuk konsumsi manusia. Anda dapat "memisahkan" mereka (itu istilah sebenarnya!), Baik dalam kode dengan sesuatu seperti gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html , dengan utilitas baris perintah seperti c++filt, atau dengan berbagai demangler online seperti demangler.com .
cincodenada
33

Untuk pernyataan statis, C ++ 11 diperkenalkan decltypeyang cukup berguna dalam skenario tertentu.

Nae
sumber
12

Jika Anda memiliki variabel

int k;

Anda bisa mendapatkan tipenya menggunakan

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

Lihat utas berikut di SO: Pertanyaan serupa

Amit
sumber
9

Perbedaan utama antara C ++ dan Javascript adalah C ++ adalah bahasa dengan tipe statis, sedangkan javascript bersifat dinamis.

Dalam bahasa yang diketik dinamis, sebuah variabel dapat berisi apa saja, dan tipenya diberikan oleh nilai yang dimilikinya, saat demi saat. Dalam bahasa tipe statis, tipe variabel dideklarasikan, dan tidak bisa diubah.

Mungkin ada pengiriman dinamis dan komposisi objek dan subtipe (pewarisan dan fungsi virtual) serta pengiriman statis dan supertyping (melalui CRTP template), tetapi dalam hal apa pun jenis variabel harus diketahui oleh penyusun.

Jika Anda berada dalam posisi untuk tidak tahu apa itu atau bisa jadi, itu karena Anda merancang sesuatu karena bahasa memiliki sistem tipe dinamis.

Jika itu kasusnya, Anda sebaiknya memikirkan kembali desain Anda, karena akan memasuki negeri yang tidak sesuai dengan bahasa yang Anda gunakan (kebanyakan seperti berjalan di jalan raya dengan ulat, atau di dalam air dengan mobil)

Emilio Garavaglia
sumber
Jika C ++ memiliki perubahan dinamis maka saya pikir itu akan menjadi hebat dan typeof dan parseInt, fungsi parseFloat juga akan berguna tetapi saya tidak tahu mengapa pembuat C ++ membuatnya terlalu sulit, misalnya! yang mengatakan baik untuk menulis cout << "String"
Waqas Tahir
tekad adalah yang terbaik !!!! #include <sstream> string str ("1912"); int strtointval; stringstream (str) >> strtointval;
Waqas Tahir
@Waqas Eh, apa? Orang-orang yang mengatakan itu yang terbaik adalah orang-orang yang mendefinisikan bahasa tersebut, dan IMO mereka memiliki cukup banyak keputusan akhir dalam segala hal yang berkaitan dengan itu - praktik pengkodean yang baik, misalnya. Bisakah Anda mengatur ulang komentar itu agar lebih masuk akal?
Dana Gugatan Monica
Saya sangat tidak setuju. Java, C #, PHP, Perl, Python, dan sebagainya dirancang dalam C dan C ++ dan mereka bukan ulat. (Saat Anda membuat aplikasi database untuk membuka tabel variabel dari database 'tidak diketahui', Anda perlu mengontrol jenis bidang ke skema variabel dan sebaliknya dengan cara yang 'sangat' dimanik;))
TomeeNS
@TomeeNS: Tidak. Mereka ditulis dalam C dan C ++, tidak dirancang . Mereka dirancang untuk melakukan tugasnya. Mereka memiliki tipe dinamis meskipun C dan C ++ sendiri tidak. Tidak ada yang aneh dengan itu.
Emilio Garavaglia
8

Biasanya, ingin mencari tipe variabel di C ++ adalah pertanyaan yang salah. Ini cenderung menjadi sesuatu yang Anda bawa dari bahasa prosedural seperti misalnya C atau Pascal.

Jika Anda ingin membuat kode untuk perilaku yang berbeda tergantung pada tipenya, coba pelajari tentang misal kelebihan beban fungsi dan pewarisan objek . Ini tidak akan langsung masuk akal pada hari pertama Anda menggunakan C ++, tetapi terus lakukan.

Pontus Gagge
sumber
Tidak juga, katakanlah Anda memiliki Objek kelas, dan Buku subkelas. Sekarang bayangkan Anda memiliki Kotak yang dapat menyimpan banyak Objek, tetapi karena alasan tertentu Anda ingin mencantumkan semua Buku di dalamnya. Memeriksa jenisnya jauh lebih bersih kemudian harus menambahkan metode "tipe" ke Objek dan kemudian menimpanya di Buku untuk mengembalikan sesuatu seperti "buku"
Paulo Cesar
Seperti aturan lainnya, ada pengecualian (karena itu 'biasanya' saya!), Dan kontainer cenderung menambah kompleksitas pada teori tipe. Saya tidak pernah terlalu menyukai container-of-polymorphic-objects ... dalam banyak kasus, jenis container seragam dengan template sudah cukup dan jauh lebih bersih.
Pontus Gagge
Apakah Anda tidak menggunakan template?
Bryan Grace
6

Saya yakin saya memiliki kasus penggunaan yang valid untuk menggunakan typeid (), cara yang sama berlaku untuk menggunakan sizeof (). Untuk fungsi template, saya perlu membuat kode kasus khusus berdasarkan variabel template, sehingga saya menawarkan fungsionalitas dan fleksibilitas maksimum.

Ini jauh lebih kompak dan dapat dipelihara daripada menggunakan polimorfisme, untuk membuat satu contoh fungsi untuk setiap jenis yang didukung. Bahkan dalam hal ini saya mungkin menggunakan trik ini untuk menulis badan fungsi hanya sekali:

Perhatikan bahwa karena kode menggunakan templat, pernyataan sakelar di bawah ini harus menyelesaikan secara statis menjadi hanya satu blok kode, mengoptimalkan semua kasus palsu, AFAIK.

Pertimbangkan contoh ini, di mana kita mungkin perlu menangani konversi jika T adalah satu jenis vs jenis lainnya. Saya menggunakannya untuk spesialisasi kelas untuk mengakses perangkat keras di mana perangkat keras tersebut akan menggunakan jenis myClassA atau myClassB. Jika ada ketidakcocokan, saya perlu menghabiskan waktu untuk mengonversi data.

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
}
Dan Truong
sumber
1
TypeId: Saya tidak dapat menggunakan typeid () di Arduino. Juga typeid () adalah runtime cek, tidak waktu kompilasi sehingga tidak dapat digunakan untuk menghasilkan kode dioptimalkan.
Dan Truong
1
Ya, tidak, ini tidak melakukan apa yang Anda kira. typeidtidak bisa menjadi pemeriksaan waktu kompilasi statis - menurut definisi - jadi ini tidak memfasilitasi pengoptimalan apa pun. For a template function, I need to special case the code based on the template variableBenar, jadi yang Anda inginkan adalah polimorfisme statis melalui idiom CRTP. Inilah yang dicapai.
underscore_d
4

Saya tidak yakin apakah jawaban saya akan membantu.

Jawaban singkatnya adalah, Anda tidak benar-benar perlu / ingin mengetahui jenis variabel untuk menggunakannya.

Jika Anda perlu memberikan tipe ke variabel statis, maka Anda dapat menggunakan auto.

Dalam kasus yang lebih canggih di mana Anda ingin menggunakan "auto" di kelas atau struct, saya sarankan menggunakan template dengan jenis deklarasi.

Misalnya, Anda menggunakan library orang lain dan memiliki variabel yang disebut "unknown_var" dan Anda ingin memasukkannya ke dalam vektor atau struct, Anda dapat melakukan ini sepenuhnya:

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

Semoga ini membantu.

EDIT: Untuk ukuran yang baik, berikut adalah kasus paling kompleks yang dapat saya pikirkan: memiliki variabel global jenis yang tidak diketahui. Dalam hal ini Anda membutuhkan c ++ 14 dan variabel template.

Sesuatu seperti ini:

template<typename T> vector<T> global_var;

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

Ini masih agak membosankan tetapi sedekat mungkin dengan bahasa tanpa ketikan. Pastikan setiap kali Anda mereferensikan variabel template, selalu letakkan spesifikasi template di sana.

gohongyi
sumber
2
#include <typeinfo>

...
string s = typeid(YourClass).name()
rad
sumber
0

Jika Anda perlu membuat perbandingan antara kelas dan tipe yang diketahui, misalnya:

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

Anda dapat menggunakan baris perbandingan ini:

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

yang memeriksa typeidnama yang berisi tipe string (nama typeid memiliki data rusak lainnya, jadi sebaiknya lakukan a s1.find(s2)daripada ==).

jackw11111
sumber
-2

Anda pasti bisa memilih di typeid(x).name()mana x adalah nama variabel. Ini sebenarnya mengembalikan pointer char const ke tipe data. Sekarang, lihat kode berikut.

#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;
}

Perhatikan bagaimana pertama dan kedua keduanya jika berhasil.

Pikachu
sumber
Mengenali tipe oleh karakter pertama adalah ide yang sangat buruk.
Dmitry Kuzminov
Bisakah Anda lebih spesifik Dmitry? Saya tidak mengerti maksud Anda di sini.
Pikachu
Ini bisa disingkat menjadi std::cout << "I'm a variable of type " << typeid(n).name(). (dibuat ulang untuk mencegah artefak a / an, tetapi itu dapat diperbaiki dengan pemeriksaan lain). Meskipun demikian, jika Anda benar-benar menginginkan perbandingan, itu jauh lebih baik untuk dilakukantypeid(n) == typeid(int)
Zoe