Da typeid(T).name()
den menschlichen verständlichen Namen des Typs nicht zurückgibt, hilft es uns nicht viel, wenn wir den Namen der Vorlagenargumente zu irgendeiner Klasse drucken wollen Vorlage, vor allem beim Debuggen. Wir haben oft das Gefühl, dies beim Debuggen zu schreiben:Pretty-print-Typen und Klassenvorlage zusammen mit allen seinen Vorlagenargumenten
print<Args...>(cout); //dump the names of all types to stdout!
Also schreibe ich Pretty-Print-Dienstprogramm, das mir den Namen der Klassenvorlage gibt. Nun, ist es einfacher, es durch einige Probe Nutzung zu verstehen:
print<int>(cout); //prints int
print<int, double, char>(cout); //prints int, double, char
print<std::string>(cout); //prints std::basic_string<char, .. etc>
print<std::wstring>(cout); //prints std::basic_string<wchar_t, .. etc>
print<X<int,Y<int>>>(cout); //prints X<int, Y<int>>
Intern, ich bin eine Klassenvorlage mit template_name
genannt, die mich "Y"
zurückkehrt, wenn ich Y<int>
es als Template-Argument übergeben. Hier ist, wie es teilweise für jede Benutzerklassenvorlage spezialisiert ist.
#define DEFINE_TEMPLATE_NAME(template_type) \
template<typename ... Ts>\
struct template_name<template_type<Ts...>>\
{\
static const char* name()\
{\
return #template_type;\
}\
};
und der Benutzer wird benötigt um dieses Makro zu verwenden, um seine Template-Klasse registrieren als:
DEFINE_TEMPLATE_NAME(std::basic_string);
DEFINE_TEMPLATE_NAME(std::vector);
DEFINE_TEMPLATE_NAME(X); //X is a class template
DEFINE_TEMPLATE_NAME(Y); //Y is a class template
Das funktioniert, weil die Spezialisierung template_name<template_type<Ts...>>
eine variadische Klasse-Vorlage auf Typen ist nur, was es bedeutet, würde mir den Namen der Klassenvorlage zurückgeben, solange alle Vorlagenparameter sind Typen. Es ist auch in der Lage funktions Typen und Mitglied Funktions-Typen sowie drucken:
typedef void fun(int,int);
//lets use snl::name() which returns name instead of printing!
std::cout << snl::name<fun>(); //prints : void(int,int)
std::cout << snl::name<fun*>(); //prints : void(*)(int,int)
Bitte sehen the working code here mit anderen kleinen Details. Das funktioniert bisher großartig.
Aber jetzt auf das ich verbessern und will, Unterstützung für Nicht-Typen Argumente und gemischte Vorlage Argumente tempate auch:
template<int...>
struct Z{};
//non-type template arguments : 1,2,3
snd::print<Z<1,2,3>>(cout); //should print Z<1,2,3>
//mixed template arguments : int, 100
snd::print<std::array<int,100>>(cout); //should print std::array<int,100>
Wie würde ich das tun? Wie bekomme ich den Namen einer solchen Klassenvorlage und ihrer Argumente generisch?
GCC hat einen Demaggler, der ziemlich nützliche Vorlagenklassennamen druckt ... –
@KerrekSB: Ja, aber das ist kein Standard. Ich will etwas, das überall funktioniert. – Nawaz