Poiché typeid(T).name()
non restituisce il nome comprensibile dell'uomo del tipo, non ci aiuta molto se si desidera stampare il nome degli argomenti del modello in qualche classe modello, specialmente quando eseguiamo il debug. Spesso ci sentiamo come scrivere questo in debug:Tipi di stampa e modello di classe insieme a tutti gli argomenti del modello
print<Args...>(cout); //dump the names of all types to stdout!
Così sto scrivendo utilità pretty-print, che mi dà il nome del modello di classe. Beh, è più facile capire attraverso qualche esempio dell'uso:
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>>
Internamente, sto utilizzando un modello di classe chiamata template_name
che mi riporta "Y"
quando passo Y<int>
ad esso come argomento di template. Ecco come è parzialmente specializzato per ogni modello di classe utente.
#define DEFINE_TEMPLATE_NAME(template_type) \
template<typename ... Ts>\
struct template_name<template_type<Ts...>>\
{\
static const char* name()\
{\
return #template_type;\
}\
};
E l'utente è necessario per utilizzare questa macro per registrare la sua classe template come:
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
Questo funziona perché la specializzazione template_name<template_type<Ts...>>
è un modello di classe variadic su tipi solo, il che significa che mi restituirebbe il nome del modello di classe finchè tutti i parametri del modello sono tipi. E 'anche in grado di stampare funzione-tipo e membro-funzione-tipi così:
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)
Si prega di vedere the working code here con altri piccoli dettagli. Funziona benissimo finora.
Ma ora sto migliorando su questo, e si desidera aggiungere il supporto per i non-tipi Tempate argomenti e argomenti template misti così:
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>
Come potrei farlo? Come posso ottenere genericamente il nome di tale modello di classe e i suoi argomenti?
GCC ha un demangler che stampa nomi di classi template piuttosto utili ... –
@KerrekSB: Sì, ma non è standard. Voglio qualcosa che funzioni ovunque. – Nawaz