2010-02-16 12 views
5

Esto solo necesita trabajar en g ++.plantilla C++ magia negra

Quiero una función

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

tal que:

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

no quiero que esto se haga a través de la especialización (es decir, tener que definir para cada tipo de magia que estoy esperando. para extraer algo de magia negra macro/plantilla aquí. ¿Alguien sabe cómo?)

Gracias!

+1

Ahora qué parte de eso es necesaria y qué parte estás escribiendo porque crees que es necesaria. ¿Es la clase Foo importante? Danos un caso de uso más realista. –

+1

Es un requisito bastante obvio para algún tipo de mecanismo de reflexión estática simple, que no traiga toda la gama de RTTI. – Justicle

+0

Quiero tener una función que pueda pasarla de cualquier tipo, y me devolverá el nombre del tipo. – anon

Respuesta

7

Trate typeid(Foo).name() para empezar. Parse como mejor le parezca; dependerá de la implementación (pero simplemente recuperar una cadena es portátil).

+0

typeid (Foo) .name() devolverá un nombre destrozado. (por ejemplo, 3Foo) –

+1

Parsear como mejor le parezca, por ejemplo: 'char * n = typeid (Foo) .name(); while (* n && * n <'A') ++ n; ' – Potatoswatter

4

El operador stringizing de macros puede ser lo que está buscando:

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

que han llegado con el siguiente:

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

He probado esto con g ++ y funciona bien.

También lo recibí de this SO answer.

10

Para convertir un tipo (u otro identificador) en una cadena, necesita una macro, pero una macro no puede verificar si su parámetro es un tipo válido. Para agregar comprobación de tipos en función de la plantilla puede ser añadido a la 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) 

Aquí magic(int) da la cadena "int" mientras magic(Foo) da una "‘Foo’no se declaró" error si no hay tal clase.

+0

De todas las respuestas aquí me gusta más esta respuesta porque a) Hace typechecking b) El resultado es el nombre de clase y no cualquier forma destrozada que puede ser dependiente del compilador – ardsrk

+0

Todavía no entiendo el propósito de 'more_magic' ... –

+1

more_magic existe solo para verificar que un tipo llamado" a "esté declarado y esté dentro del alcance. Sin eso podría llamar magia (%%%%) y obtener la llamada para tener éxito a pesar de que %%%% no podría haber sido un nombre legal para un tipo. – ardsrk

-1

En C++ probablemente usted está buscando plantilla de magia negra. Si es así, Modern C++ Design será útil.

+0

-1 Poco útil o relevante para la pregunta – Tomas