2011-07-15 26 views
5

Uso typedefs para casi todo, incluidas las funciones. En las últimas semanas, he estado mejorando nuestro código de C++ para adaptarme lo más exactamente posible al estándar ISO C++ 11, utilizando el borrador final (N3242) como guía.Declaraciones múltiples de funciones C++ con parámetros predeterminados

Como sabemos, hay varias declaraciones ocasionales que se filtran en nuestro código a través de externos que aparecen en más de un archivo, o typedefs que se repiten. De acuerdo con este extracto de la sección 7.1.3, página 145 de la mana anterior, esto debe ser inofensivo:

3. In a given non-class scope, a typedef specifier can be used to redefine the name of any type declared in that scope to refer to the type to which it already refers.

[ Example:

typedef struct s { /* ... */ } s; 
    typedef int I; 
    typedef int I; 
    typedef I I; 

— end example ]

Así, escribí un programa para probar esto. En su forma más simple:

typedef int (fcntype)(int, int); 
extern fcntype fcn1; 

int fcn1(int x, int y) { return x + y; } 

int main(int argc, char ** argv) { return fcn1(2, 3); } 

compilación con gcc con

-Wfatal-errors -Wswitch-default -Wswitch-enum -Wunused-parameter -Wfloat-equal -Wundef -c -Wstrict-null-sentinel -std=c++0x -pedantic -Wall -Wextra 

hay, por supuesto, no hay problemas. Dupliquemos la función decl:

typedef int (fcntype)(int, int); 
extern fcntype fcn1; 
extern fcntype fcn1; // woops. probably from an #include ... 

int fcn1(int x, int y) { return x + y; } 

int main(int argc, char ** argv) { return fcn1(2, 3); } 

Como predice la norma, no hay problemas. Vamos a hacer un cambio diferente al original:

typedef int (fcntype)(int, int=0); // default param. 
extern fcntype fcn1; 

int fcn1(int x, int y) { return x + y; } 

int main(int argc, char ** argv) { return fcn1(2); } // use the default param 

Nuevamente, sin problemas. El problema surge cuando tenemos tanto la decl duplicado y el parámetro default como esto:

typedef int (fcntype)(int, int=0); // default param. 
extern fcntype fcn1; 
extern fcntype fcn1; // FYI this is line 3 in the error message below. 

int fcn1(int x, int y) { return x + y; } 

int main(int argc, char ** argv) { return fcn1(2); } // use the default param 

y gcc se queja con

decltest.cpp:3: error: default argument given for parameter 2 of ‘int fcn1(int, int)’ 

Por supuesto, estoy limpiando el código de la manera en que debe limpiado, lo que quiere decir que estoy acorralando las decls en un archivo mejor organizado. ¿Pero es esto un error en el compilador o un malentendido mío sobre qué parámetro "es"?

Respuesta

6

En primer lugar, para la misma declaración de función con los mismos tipos, solo debe haber como máximo una declaración que defina los argumentos predeterminados. Esto se debe a §8.3.6 [dcl.fct.default]/4:

... A default argument shall not be redefined by a later declaration (not even to the same value). [ Example:

... 
void m() { 
    void f(int, int);  // has no defaults 
    f(4);     // error: wrong number of arguments 
    void f(int, int = 5); // OK 
    f(4);     // OK, calls f(4, 5); 
    void f(int, int = 5); // error: cannot redefine, even to same value 
} 
... 

end example ] ...

Además, como se notó @Sven, un argumento predeterminado no deberán aparecer en un typedef, aunque g ++ no puede alcanzar, incluso con -pedantic . Creo que clang y Visual C++ rechazan esto pero no lo he intentado.

+2

Además, nota al pie 101 (en la misma página): "Esto significa que los argumentos predeterminados no pueden aparecer, por ejemplo, en declaraciones de punteros a funciones, referencias a funciones o declaraciones typedef". Así que creo que 'typedef int (fcntype) (int, int = 0);' en sí mismo ya no debería compilarse. ¿O me estoy perdiendo algo? – Sven

+0

Ah, sí. Gracias particularmente por la referencia en el estándar. Lo he resaltado Es fascinante cómo estas cosas se apoderan de ti, lo cual es un buen argumento para pasar por el código de vez en cuando para limpiar las cosas. –

1

Su cotización estándar no se aplica aquí, ya que no está declarando el typedef varias veces, sino que lo usa varias veces.

Los argumentos predeterminados son un caso complicado, solo pueden aparecer en una declaración (y recuerde, la definición misma cuenta como una declaración, incluso poniendo el argumento predeterminado en una declaración forward y una definición es un error).

0

Esto genera el mismo error:

extern int fcn1(int, int=0); 
extern int fcn1(int, int=0); 

Así que no es sorprendente que su versión typedef no funciona.

Cuestiones relacionadas