Newsgroup: it.comp.lang.c++
Titolo: [template] specializzazioni e data member

Salve,
template<class T> struct typename_t {
    static const char* name;
    operator const char*() { return name; }
};
const char* typename_t<miotipo>::name = "miotipo" ;
L'istanziazione del template avviene quando definisco il valore di
"name", ma solo se il template lo esplicito con template<> struct
typename_t<miotipo> { ... e riscrivendo qui dentro quello che avevo nel
template, vanificandolo perché avrei preferito non riscriverlo.
Diciamo che quello che vorrei ottenere è un elenco di template
specializzati aventi ognuno un data member per tipo. Dovrei usare
l'ereditarietà in questo caso? Per il momento, la variante che
funziona è:
template<> struct typename_t<miotipo> {
    operator const char*() { return "miotipo"; }
};
E già che ci sono, vi faccio un'altra domanda. La versione runtime di
quanto sopra è un array di pair<const type_info*, typename_t<T>() );
che poi uso per inizializzare un map.
In realtà mi serve solo per i pod, ma non so se i puntatori a
type_info sono garantiti univoci per essere usati nel map, ma suppongo
di sì. Uso un puntatore perché type_info ha copy ctor privato e una
map non può avere un ref come chiave (giusto?).
Saluti
PS: ho boost

 quanto sopra è un array di pair<const type_info*, typename_t<T>() );
scusate, intendevo pair<const type_info*, const char* >, il
typename_t<T>() è l'oggetto con cui inizializzo second. Il first con
&typeid( T ) .
Saluti

alef ha scritto:
[...]
Ho riletto varie volte, ma, qualsiasi interpretazione dia al tuo msg, 
giungo a contraddizioni. Penso dovresti riformularlo. Posso solo 
sospettare cosa tu voglia fare.
Kiuhnm

 giungo a contraddizioni.
Veramente anche io. Ma ora ci provo a darne una univoca:
template<typename T> struct typename_t;
template<> struct typename_t<bool> {
    operator const char*() { return "bool"; }
};
... per un pò di pod
typedef pair<const typeinfo*, const char*> typename_pair_t;
template<typename T>
struct typename_pair_ctor {
    operator const typename_pair_t () {
        return typename_pair_t( &typeid(T), typename<T>() );
    }
};
typename_pair_t typename_pairs[] = {
    typename_pair_ctor<bool>(),
    .... per i pod di cui sopra, almeno per quelli per cui typeid
funziona
};
map<const type_info*, const char*> type_name(
    &typename_pairs[0]
    ,&typename_pairs[ sizeof(typename_pairs) /
sizeof(typename_pairs[0]) ]
);
int main() {
    a runtime:
    cout << type_name[ typeid(bool) ] << endl;
    ma potrei usare typename_t<T> in un altro template invece di
type_name
}
Il fatto di averne una per template e una per typeid è giusto per
permettermi di usarla in specializzazioni di certe altre classi utente
senza passare per la map via typeid.
Cerco di riassumere le domande/richieste:
Vorrei che il template typename_t avesse un const char* name che
definisco per ogni specializzazione, senza dover ogni volta ridefinire
l'operator di cast.
La chiave const type_info* è univoca per ogni T in &typeid( T ) ?
Aggiungo: ma type_name() con i due iteratori si fa una copia in memoria
di tutto typename_pairs[] o lo usa come base per i suoi dati?
In sostanza: usando boost::any::type() vorrei stamparne il nome, almeno
per i pod. std::typeinfo::name() è implementation defined, e nel mio
caso (gcc3 su cygwin) non corrisponde a quella del compilatore.
Grazie

 l'operator di cast.
Ti va bene qualcosa del genere?
===
#include <iostream>
#define MAKE_STRING(TYPE)			\
	template <>						\
	struct string_t<TYPE>			\
	{								\
		static const char* str;		\
	};								\
	const char* string_t<TYPE>::str = #TYPE;
template <typename T>
struct string_t;
MAKE_STRING(bool);
MAKE_STRING(signed int);
MAKE_STRING(unsigned int);
MAKE_STRING(char);
MAKE_STRING(signed char);
MAKE_STRING(unsigned char);
template<typename T>
struct typename_t
{
	static const string_t<T> n;
     operator const char*() { return n.str; }
};
int main()
{
	std::cout << static_cast<const char*>(typename_t<bool>()) << std::endl;
	std::cout << static_cast<const char*>(typename_t<int>()) << std::endl;
	std::cout << static_cast<const char*>(typename_t<char>()) << std::endl;
	std::cout << static_cast<const char*>(typename_t<signed char>()) << 
std::endl;
	std::cout << static_cast<const char*>(typename_t<unsigned char>()) << 
std::endl;
	std::cout << static_cast<const char*>(typename_t<unsigned>()) << std::endl;
}
===
Per il resto, puoi consultare la documentazione oppure aspettare che 
risponda qualcun altro.
Kiuhnm

 Kiuhnm
Il tuo nick mi ricorda le password basate sulla geometria della
tastiera. Gtrdcv.
Saluti

 tastiera. Gtrdcv.
Ti garantisco che le mie pw non sono così, però!
Kiuhnm