2009-09-04 13 views
6

Tengo este grave problema. Tengo una enumeración dentro de 2 espacios de nombres como esto:Conflicto entre un espacio de nombres y una definición

namespace FANLib { 
namespace ERROR { 

    enum TYPE { 

     /// FSL error codes 
     FSL_PARSER_FILE_IERROR,... 

y otra parte de mi código, utilizar de esta manera:

FANLib::Log::internalLog(FSLParser::FILE_IERROR, file_ierror, true, FANLib::ERROR::FSL_PARSER_FILE_IERROR); 

Todo compila bien y bien, pero si resulta que incluyen " windows.h ", obtengo errores! El problema está en "WinGDI.h" que tiene esta línea:

#define ERROR    0 

y hace que el compilador piensa que, después de FANLib :: ..., hay un cero! El error que consigo es:

de error 1 C2589 de error: 'constante': token ilegal en el lado derecho de la '::'

error 2 error C2059: error de sintaxis: '::'

error 3 error C2039: 'FSL_PARSER_FILE_IERROR': no ​​es un miembro de '`espacio de nombres global''

¿hay algo que pueda hacer al respecto, sin tener que cambiar mis espacios de nombres debido a algún imprudente #define? He leído en otra publicación que podría #undef ERROR, pero ¿qué tan seguro es eso?

Respuesta

14

Generalmente, debe evitar el uso de identificadores de mayúsculas, ya que se utilizan para las macros. En este caso, cambiaría el nombre del espacio de nombres.

(Como nota al margen, <windows.h>#define s otras cosas como GetPrinter y de hecho se vuelve molesto. Yo suelo ir con #undef a continuación. También ayuda para incluir sólo <windows.h> en archivos .cpp y asegurarse el ámbito afectado por la cabecera es lo más pequeño posible.)

+0

Usted hace varios puntos muy buenos. Desafortunadamente, solo puedo dar tu respuesta un voto. – sbi

+2

Agregaría que la "convención aceptada de forma estándar" es que los identificadores que son todos mayúsculas son macros. –

+4

Windows.h toma todas las "convenciones aceptadas de forma estándar", las arroja por la ventana y declara macros por todas ellas. Pero sí, buen consejo. No utilice mayúsculas para nada que no sea #defines, y no permita que windows.h sea visible en sus encabezados. – jalf

1

Creo que no será un problema si #desdef. Pero tendrías que hacerlo en cualquier lugar donde uses tanto tu enum & windows.h. Lo mejor sería cambiar el nombre de tu espacio de nombres.

2

Cambiar el nombre de su espacio de nombres es la solución más limpia, más segura y más interoperable.

2

Saltando en el vagón de "cambiar el nombre de tu espacio de nombres", simplemente porque ERROR es un nombre demasiado común y vago. Encuentra algo más descriptivo.

1

Es posible que desee refactorizar su código para que ese #include solo aparezca cuando sea necesario. La forma "correcta" puede incluso implicar la creación de archivos y encabezados separados que incluyen interfaces con las funciones a las que llamará desde windows.h

Sin embargo, si solo quiere una solución simple y le preocupan los efectos secundarios de #undef ERROR , acaba de redefinir el error después de que haya terminado con su nulidad:

 
#undef ERROR 
namespace ERROR { 
#define ERROR 0 

que tendría que hacer este error cada vez que se conoce (y no en una cadena).

Habiendo dicho eso, debería estar bien si simplemente no define ERROR. Solo afectaría cómo el preprocesador C maneja ERROR (o más bien cómo no) desde ese punto en adelante.

Por cierto, generalmente he visto nombres en mayúsculas que solo se usan para especificar constantes, no para tipos y espacios de nombres. Me reconsiderar mi convención de nomenclatura si fuera tú ..

+0

Mala idea; no es extraño que Microsoft cambie # define's en las versiones más nuevas de SDK. Esto sucede incluso para las constantes (aunque probablemente ERROR no se verá afectado) – MSalters

+0

Tiene razón, no es una buena práctica, y llevaría fácilmente a efectos secundarios difíciles de depurar más adelante para asumir que el valor de una etiqueta siempre será una dado constante. Pero en mi defensa, no fue mi primera sugerencia ni la última, y ​​nunca dije nada sobre una buena solución. Dije que era una solución simple (o una solución rápida), y esos tipos de correcciones generalmente causan problemas para depurar ¡efectos secundarios! – lcv

0

La mejor solución es cambiar el esquema de denominación para evitar todo en mayúsculas, como han sugerido otros:

namespace FANLib { 
    namespace Error { 
    enum Type { 
     /// FSL error codes 
     FSL_Parser_File_IError, ... 

también fuera de los límites: identificadores que comienza con _ o __. (Es más complicado que eso, pero su vida será más simple si solo evita todos los nombres que comiencen con un guión bajo)

0

Si no usa GDI, puede definir NOGDI para suprimir las macros de definición en WinGDI.h. Here puede encontrar otras opciones útiles.

0

Los identificadores que comienzan con E y un dígito o E y una letra en mayúscula se deben tratar como reservados, ya que tales nuevas macros podrían agregarse al <errno.h>.

Cuestiones relacionadas