Zum Beispiel:
int a = 12;
cout << typeof(a) << endl;
Erwartetes Ergebnis:
int
Zum Beispiel:
int a = 12;
cout << typeof(a) << endl;
Erwartetes Ergebnis:
int
Hierfür könnte man eine Traits-Klasse verwenden. Etwas wie:
#include <iostream>
using namespace std;
template <typename T> class type_name {
public:
static const char *name;
};
#define DECLARE_TYPE_NAME(x) template<> const char *type_name<x>::name = #x;
#define GET_TYPE_NAME(x) (type_name<typeof(x)>::name)
DECLARE_TYPE_NAME(int);
int main()
{
int a = 12;
cout << GET_TYPE_NAME(a) << endl;
}
Le site DECLARE_TYPE_NAME
define existiert, um Ihnen das Leben zu erleichtern, indem Sie diese Traits-Klasse für alle Typen deklarieren, die Sie voraussichtlich benötigen werden.
Dies könnte nützlicher sein als die Lösungen, die typeid
weil Sie die Kontrolle über die Ausgabe haben. Zum Beispiel, mit typeid
para long long
auf meinem Compiler ergibt "x".
In C++11 haben wir decltype. In Standard-C++ gibt es keine Möglichkeit, den genauen Typ einer mit decltype deklarierten Variablen anzuzeigen. Wir können boost typeindex verwenden, d.h. type_id_with_cvr
(cvr steht für const, volatile, reference), um den Typ wie unten zu drucken.
#include <iostream>
#include <boost/type_index.hpp>
using namespace std;
using boost::typeindex::type_id_with_cvr;
int main() {
int i = 0;
const int ci = 0;
cout << "decltype(i) is " << type_id_with_cvr<decltype(i)>().pretty_name() << '\n';
cout << "decltype((i)) is " << type_id_with_cvr<decltype((i))>().pretty_name() << '\n';
cout << "decltype(ci) is " << type_id_with_cvr<decltype(ci)>().pretty_name() << '\n';
cout << "decltype((ci)) is " << type_id_with_cvr<decltype((ci))>().pretty_name() << '\n';
cout << "decltype(std::move(i)) is " << type_id_with_cvr<decltype(std::move(i))>().pretty_name() << '\n';
cout << "decltype(std::static_cast<int&&>(i)) is " << type_id_with_cvr<decltype(static_cast<int&&>(i))>().pretty_name() << '\n';
return 0;
}
Sie können auch c++filt mit der Option -t (Typ) verwenden, um den Typnamen zu entschlüsseln:
#include <iostream>
#include <typeinfo>
#include <string>
using namespace std;
int main() {
auto x = 1;
string my_type = typeid(x).name();
system(("echo " + my_type + " | c++filt -t").c_str());
return 0;
}
Nur unter Linux getestet.
Die anderen Antworten, die RTTI (typeid) beinhalten, sind wahrscheinlich das, was Sie wollen, solange:
Die Alternative (ähnlich wie die Antwort von Greg Hewgill) besteht darin, eine Kompilierzeittabelle mit Merkmalen zu erstellen.
template <typename T> struct type_as_string;
// declare your Wibble type (probably with definition of Wibble)
template <>
struct type_as_string<Wibble>
{
static const char* const value = "Wibble";
};
Beachten Sie, dass Sie, wenn Sie die Deklarationen in ein Makro verpacken, aufgrund des Kommas Probleme haben werden, Namen für Schablonentypen zu deklarieren, die mehr als einen Parameter haben (z.B. std::map).
Um auf den Namen des Typs einer Variablen zuzugreifen, brauchen Sie nur
template <typename T>
const char* get_type_as_string(const T&)
{
return type_as_string<T>::value;
}
Wie von Scott Meyers in Effective Modern C++ erläutert,
Anrufe an
std::type_info::name
sind keine Garantie dafür, dass sie etwas Vernünftiges ergeben.
Die beste Lösung besteht darin, den Compiler während der Typerkennung eine Fehlermeldung generieren zu lassen, zum Beispiel,
template<typename T>
class TD;
int main(){
const int theAnswer = 32;
auto x = theAnswer;
auto y = &theAnswer;
TD<decltype(x)> xType;
TD<decltype(y)> yType;
return 0;
}
Das Ergebnis sieht dann je nach Compiler etwa so aus,
test4.cpp:10:21: error: aggregate ‘TD<int> xType’ has incomplete type and cannot be defined TD<decltype(x)> xType;
test4.cpp:11:21: error: aggregate ‘TD<const int *> yType’ has incomplete type and cannot be defined TD<decltype(y)> yType;
Daher erfahren wir, dass x
ist der Typ int
, y
ist der Typ const int*
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
3 Stimmen
Hier ist eine Zusammenfassung von Howards Langformlösung, die jedoch mit einem ketzerischen einzeiligen Makro umgesetzt wurde:
#define DEMANGLE_TYPEID_NAME(x) abi::__cxa_demangle(typeid((x)).name(), NULL, NULL, NULL)
. Wenn Sie plattformübergreifende Unterstützung benötigen: Verwenden Sie .#ifdef
,#else
,#endif
um ein Makro für andere Plattformen wie MSVC bereitzustellen.0 Stimmen
Mit expliziteren, für Menschen lesbaren Anforderungen: stackoverflow.com/questions/12877521/
3 Stimmen
Wenn Sie dies nur zum Debuggen verwenden, sollten Sie Folgendes in Betracht ziehen
template<typename T> void print_T() { std::cout << __PRETTY_FUNCTION__ << '\n'; }
. Dann verwenden Sie z.B.print_T<const int * const **>();
wird gedrucktvoid print_T() [T = const int *const **]
zur Laufzeit und bewahrt alle Qualifier (funktioniert in GCC und Clang).0 Stimmen
@Henri,
__PRETTY_FUNCTION__
ist nicht Standard C++ (die Anforderung steht im Titel der Frage).