2010-02-16 24 views
5

Questo funziona solo in g ++.C++ template black magic

Voglio una funzione

template<typename T> std::string magic(); 

tale che:

Class Foo{}; magic<Foo>(); // returns "Foo"; 
Class Bar{}; magic<Bar>(); // returns "Bar"; 

Non voglio questo per essere fatto tramite la specializzazione (cioè dover definire magica per ogni tipo spero. per estrarre qui alcuni macro/modelli di magia nera. Qualcuno sa come?)

Grazie!

+1

Ora quale parte di ciò è necessaria e quale parte stai scrivendo semplicemente perché pensi che sia necessario. La classe Foo è importante? Dacci un caso d'uso più realistico. –

+1

È un requisito abbastanza ovvio per una sorta di semplice meccanismo di riflessione statica, che non introduce l'intera gamma di RTTI. – Justicle

+0

Voglio avere una funzione che posso passargli qualsiasi tipo, e mi restituirà il nome del tipo. – anon

risposta

7

Prova typeid(Foo).name() per un inizio. Analizza come ritieni opportuno; dipenderà dall'implementazione (ma semplicemente ottenere una stringa è portatile).

+0

typeid (Foo) .name() restituirà un nome storpiato. (ad esempio 3Foo) –

+1

Analizza come ritieni opportuno, ad esempio: 'char * n = typeid (Foo) .name(); while (* n && * n <'A') ++ n; ' – Potatoswatter

4

L'operatore stringizing sulle macro può essere quello che stai cercando:

#define MAGICCLASSNAME(str) std::string magic(#str) 
class Foo{}; MAGICCLASSNAME(foo) 
1

sono venuto su con il seguito:

#include <iostream> 
#include <string> 
#include <typeinfo> 

using namespace std; 
class Foo{}; 
class Bar{}; 

template<typename T> 
inline std::string magic(const T& obj) 
{ 
return typeid(obj).name(); 
} 

int main() 
{ 
Foo a; 
cout << magic<Foo>(a); // returns "Foo"; 
} 

Ho provato questo con g ++ e funziona bene.

Anche io ho capito da this SO risposta.

10

Per convertire un tipo (o un altro identificatore) in una stringa è necessaria una macro, ma una macro non può controllare se il parametro è un tipo valido. Per aggiungere il tipo il controllo di una funzione template può essere aggiunto alla macro:

template<typename T> 
std::string magic_impl(const char *name) { return name; } 

#define more_magic(a) magic_impl<a>(#a) 
#define magic(a) more_magic(a) 

Qui magic(int) dà la stringa "int" mentre magic(Foo) dà un "‘Foo’non è stato dichiarato" errore se non c'è tale classe.

+0

Di tutte le risposte date qui mi piace questa risposta la migliore perché a) Fa typechecking b) Il risultato è il nome della classe e non qualsiasi forma straziata che potrebbe essere dipendente dal compilatore. – ardsrk

+0

Ancora non capisco lo scopo di 'more_magic' ... –

+1

more_magic esiste solo per verificare che un tipo denominato" a "sia dichiarato ed è in ambito. Senza quello potrei chiamare magic (%%%%) e ottenere la chiamata per riuscire anche se %%%% non potrebbe essere stato un nome legale per un tipo. – ardsrk

-1

In C++ probabilmente stai cercando il modello di magia nera. In tal caso, sarà utile il Modern C++ Design.

+0

-1 Non molto utile né pertinente alla domanda – Tomas