2010-02-16 14 views
5

Dies benötigt nur Arbeit in g ++.C++ Vorlage schwarze Magie

Ich möchte eine Funktion

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

, so dass:

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

Ich will nicht diese über Spezialisierung durchgeführt werden (dh mit für jede Art Magie zu definieren, ich hoffe. um etwas Makro/Schablone schwarze Magie hier zu ziehen. Weiß jemand wie?)

Danke!

+1

Nun, welcher Teil davon ist notwendig und welcher Teil schreiben Sie gerade, weil Sie denken, dass es gebraucht wird. Ist die Klasse Foo wichtig? Gib uns einen realistischeren Anwendungsfall. –

+1

Es ist eine ziemlich offensichtliche Anforderung für einen einfachen statischen Reflexionsmechanismus, der nicht den vollen Umfang von RTTI einbringt. – Justicle

+0

Ich möchte eine Funktion haben, die ich jedem Typ übergeben kann, und es wird für mich den Namen des Typs zurückgeben. – anon

Antwort

7

Versuchen typeid(Foo).name() für einen Start. Analysieren Sie, wie Sie es für richtig halten; wird implementationsabhängig sein (aber einfach einen String zurück zu bekommen ist portabel).

+0

typeid (Foo) .name() gibt einen ungültigen Namen zurück. (z. B. 3Foo) –

+1

Parsen, wie Sie es für richtig halten, zB: 'char * n = typeid (Foo) .name(); while (* n && * n <'A') ++ n; ' – Potatoswatter

4

Die Zeichenfolgen Operator auf Makros kann das sein, was Sie suchen:

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

Ich habe mit dem unten kommen:

#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"; 
} 

Getestet habe ich diese mit g ++ und funktioniert gut.

Auch ich habe es von this SO Antwort.

10

Um einen Typ (oder einen anderen Bezeichner) in einen String zu konvertieren, benötigen Sie ein Makro, aber ein Makro kann nicht prüfen, ob es sich um einen gültigen Typ handelt. So fügen Sie Art, die eine Template-Funktion Überprüfung kann dem Makro hinzugefügt werden:

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) 

Hier magic(int) gibt dem String "int" während magic(Foo) gibt einen „‚Foo‘wurde nicht deklariert“ Fehler, wenn es keine solche Klasse ist.

+0

Von allen hier gegebenen Antworten mag ich diese Antwort am besten, weil a) sie typechecking b) Das Ergebnis ist der Klassenname und nicht irgendeine fehlerhafte Form kann compilerabhängig sein. – ardsrk

+0

Ich verstehe immer noch nicht den Zweck von 'more_magic' ... –

+1

more_magic existiert nur um zu überprüfen, dass ein Typ namens" a "deklariert ist und im Geltungsbereich ist. Ohne das könnte ich Magie (%%%%) nennen und den Aufruf zum Erfolg bringen, obwohl %%%% kein legaler Name für einen Typ sein konnte. – ardsrk

-1

In C++ wahrscheinlich suchen Sie Vorlage schwarze Magie. Wenn ja, wird Modern C++ Design hilfreich sein.

+0

-1 Nicht sehr hilfreich oder relevant für die Frage – Tomas