2012-03-04 21 views
11

¿Hay alguna manera de usar direcciones de función en expresiones constantes?¿Por qué las direcciones de función no son expresiones constantes?

void foo() 
{} 

int main() 
{ 
    static_assert(&foo, "test error"); 
} 

Esto no se compilará.

C2057 de error: se esperaba expresión constante

La intención de esto es que quiero comparar dos direcciones de las funciones en tiempo de compilación.

Respuesta

6

Definitivamente es un error del compilador.

Las funciones se pueden utilizar como argumento de plantilla para la plantilla, lo que significa que son expresiones const. (Ver ideone).

Además, el código anterior compila bien con gcc 4.6.1, aunque ideone no lo compila, pero ideone usa gcc-4.5.1 que tiene errores con respecto a su código.

+4

Creo que esto podría ser un poco más complicado. Uno de los problemas con las direcciones de funciones es que el compilador no necesariamente * sabe * su valor (puede definirse en una unidad de traducción diferente o no definirse en absoluto. ¿Cuál es el resultado esperado (en * tiempo de compilación *) de '& foo 'para esos casos? (No digo que no se pueda hacer, esa expresión se considera * odr-use *, por lo que el compilador puede suponer que se debe definir y dejar que el enlazador resuelva que la dirección es incorrecta si no está definida, pero Me gustaría ir a la norma para una respuesta autorizada a la pregunta. –

+2

Las funciones se conocen en tiempo de compilación, pero sus direcciones no lo son. Los nombres simbólicos se utilizan en tiempo de compilación para el enlazador a la memoria de mapa más tarde. Para complicar aún más las cosas, después las plantillas se introdujeron en C++, los enlazadores casi universalmente comenzaron a plegar funciones que tienen un código compilado idéntico. Por lo tanto ** dos funciones diferentes podrían tener la misma dirección en tiempo de ejecución **. No se espera que el compilador lo sepa. –

+0

S Las funciones ince pueden reubicarse en el momento de la carga (piense en la DLL de Windows) y luego no puedo ver cómo se puede conocer '& foo', en general, hasta que se ejecute el programa. –

3

Este es mi entendimiento, Fwiw:

Una función tipo se conoce un tiempo de compilación, sino una dirección de función sólo se conoce en tiempo de enlace. Por lo tanto, puede usar tipos de funciones como parámetros de plantilla, pero las direcciones no son constantes/conocidas en tiempo de compilación.

En su código de ejemplo, el compilador podría deducir que la dirección es distinta de cero en el momento de la compilación, pero no podrá conocer la dirección específica en ese momento. Sin embargo, esto no es un error del compilador.

+0

Las direcciones ni siquiera se conocen en el momento del enlace. El código a menudo se reubica al momento de la carga. –

+1

Es cierto, pero las direcciones relativas dentro del mismo módulo cargable * son * conocidas en el tiempo de enlace, de modo que los saltos de función pueden ser "cableados". Mi punto es que la dirección de la función se puede tomar lógicamente en tiempo de ejecución (es decir: el lenguaje garantiza que esto es legal), pero no un tiempo de compilación. – Nick

Cuestiones relacionadas