2009-05-06 17 views
6

A veces necesito aprender el tipo de expresión mientras programo en C o C++. A veces hay un buen IDE o documentación existente para ayudarme, pero a veces no. A menudo me siento una construcción de este tipo podría ser útil:Determinación del tipo de expresión

void (*myFunc)(int); 
printf("%s", nameoftype(myFunc)); //"void (*)(int)" 
int i, unsigned int u; 
printf("%s", nameoftype(i+u)); //"unsigned int" 

Esto es especialmente cierto para C++; pensar en los descriptores de los objetos const: ¿devuelven una referencia constante o una copia? Piense en moldes dinámicos y clases con plantillas.

¿Cómo puedo hacer esto? (es decir, aprender el tipo de una expresión)

Uso GCC pero, hasta donde yo sé, no tiene esa extensión. Así que supongo que tengo curiosidad sobre cómo las personas resuelven este problema. (Tanto las soluciones en tiempo de compilación como en tiempo de ejecución son bienvenidas.)

Respuesta

1

¿Qué estás buscando? ¿Inferencia de tipo automática o buscando el tipo para que pueda declarar una variable correctamente de forma manual? (sus propias respuestas parecen que quiere tener la segunda). En este caso, considere el uso de Geordi:

<litb> make type pointer to function taking pointer to array of 10 int returning void 
<geordi> void (*)(int (*)[10]) 

<litb> geordi: { int a = -1; unsigned int b = 0; cout << ETYPE(a + b), ETYPE_DESC(a + b), (a + b); } 
<geordi> rvalue unsigned int, rvalue unsigned integer, 4294967295 

<litb> geordi: << TYPE_DESC(void (*)(int (*)[10])) 
<geordi> pointer to a function taking a pointer to an array of 10 integers and returning nothing 

tipo automático de la inferencia no es actualmente posible sin bibliotecas cooperadoras como boost.typeof, que utilizará como extensiones del compilador __typeof__ para GCC. Siguiente C++ obtendrá auto (con semántica diferente a la actual auto) y podrá hacerlo, junto con decltype para obtener el tipo de una expresión.

Si se puede vivir con salir del contexto local, siempre se puede crear una plantilla de función como esta:

template<typename T> void f(T t) { /* ... */ } 
int main() { int a = -1; unsigned int b = 0; f(a + b); } 
+0

Lo siento, pensé que era obvio que no estaba buscando la inferencia tipográfica. Aunque estoy deseoso de ver un nuevo código sphagetti C++ 0x con variables automáticas por todos lados :) - Wow, había olvidado que Geordi podría escribir descripciones. Echaré un vistazo a la implementación. También gracias por el enlace KDevelop. Podría hacer una alternativa a Eclipse. – aib

+1

Geordi link was dead - aquí está la ubicación actual en github: https://github.com/Eelis/geordi – KarlC

2

C++ tiene un operador typeid;

typeid(expression).name() 

devolvería un nombre definido por la implementación del tipo de la expresión. Por desgracia, por lo general no es legible por humanos.

+3

Si youare Con g ++ es el nombre mangeled. A continuación, puede usar la herramienta de línea de comandos 'C++ filt' para desregularla. –

+0

Ah, nunca he usado C++ filt. Lo investigaré, gracias. – aib

+0

Actualmente este enfoque no se recomienda, y se debe considerar en algún caso obsoleto. La razón por la que se imprime tipo, el tipo de salida es engorroso. ¡Además, a veces imprime tipo no válido! Los ejemplos exactos se explican claramente en el nuevo "C++ moderno efectivo", Capítulo 1, punto 4. – likern

13

veces simplemente hacer:

int ***a = expression; 

y buscar la "< tipo de expresión > no se pueden asignar a puntero a int^3" de error. Esta parece ser la solución más portátil.

+1

Algunos compiladores de C antiguos lo permitirán. :-( –

+3

Creo una clase 'FailAssign' y luego trato de asignar una expresión a una instancia de la clase. De esta forma, no hay autoconversiones activadas (incluso con errores). –

+2

Hmm, buena idea.¡Aunque mi camino te permite declarar un triple puntero! ¿Con qué frecuencia haces eso? :) – aib

1

Pruebe Boost.Typeof para ver si se ajusta.

+0

Parece una buena solución para la inferencia de tipo, pero no vi una macro que evalúe, o una función que devuelve una cadena que contiene el nombre de tipo. Uno podría agregarse, sin embargo, ya que usa macros centrales REGISTER_(). – aib

Cuestiones relacionadas