2011-06-08 8 views
6

¿Qué sucede si dos libs diferentes definen la misma enumeración y necesito usar ambas libs en el mismo proyecto?Enum conflictivas

enum {Mes enero = 0, febrero, ..., Diciembre}

Gracias.

P.S. Es C. Sin espacios de nombres. No podré mantenerlos separados. Necesita alguna solución.

¿Qué es el enum linkage? ¿Interno o externo? C libs utilizadas en el proyecto C++. Se aplica la etiqueta C++.

+2

Espero que las dos bibliotecas usen espacios de nombres separados? – GWW

+4

Esto realmente no es diferente a múltiples definiciones conflictivas de tipos, variables o funciones. –

+1

¿Esto es C o C++? No son un idioma –

Respuesta

5

magia último mal solución asistente: si los espacios de nombres no ayudan (por cualquier razón), y usted no puede evitar la inclusión de ambas definiciones en el mismo archivo, utilice una macro:

#define Month File_A_Month 
#include "file_a.h" 
#define Month File_B_Month 
#include "file_b.h" 
#undef Month 

En el archivo, nunca use Month, solo File_A_Month o File_B_Month. No estoy seguro de la corrección de los estándares de esta práctica.

Puede que tenga que definir todos los enum miembros de manera similar para evitar enfrentamientos, y es probable que desee poner este hacker malvado en un archivo llamado files_a_and_b.h. Por supuesto, en su caso las definiciones son idénticas, por lo que no debería necesitar recurrir a esto, pero dejo esta respuesta aquí para una posteridad menos afortunada.

+0

+1, no había pensado en eso. –

+1

+1. Es malo, pero intentaré ser cuidadoso. – pic11

+0

Los nombres de constante de enumeración idéntica causarán conflictos de nombres incluso si las definiciones son idénticas. Pero, como se mencionó, aplicar el macro hack a cada uno de los nombres enum hará el truco. –

11

C libs utilizado en C++ project. se aplica la etiqueta C++

Dado que se usan en proyectos de C++, entonces se puede utilizar espacio de nombres al incluirlos en código C++ como:

// C files 
//libone.h 
enum Month {January=0, February, ..., December} 

//libtwo.h 
enum Month {January=0, February, ..., December} 

/////////////////////////////////////////////////////////////////// 
//C++ files 

//lib.hpp 
namespace LibOne 
{ 
    #include "libone.h" 
} 
namespace LibTwo 
{ 
    #include "libtwo.h" 
} 

//Usage in C++ 
LibOne::Month m1 = LibOne::January; 
LibTwo::Month m2 = LibTwo::January; 
+0

+1. Pero tengo demasiado código que ya usa lib_1. – pic11

+0

@ pic11: No sé cómo es la estructura de tu código. Pero una cosa es segura, cada vez que agrega una nueva biblioteca a sus proyectos C++, lo que causa conflictos de nombres, entonces siempre puede incluir la nueva biblioteca en un espacio de nombres diferente. – Nawaz

+0

Escribo C++ API y la misma enumeración ya está definida en el espacio de nombres de mi lib. El código de usuario puede pasar el valor enum a mi API, que a su vez pasa el mismo valor a C API. – pic11

2

Lo ideal sería que los dos están en diferentes espacios de nombres.

De lo contrario, puede evitar incluir ambas definiciones en una sola unidad de compilación.

EDIT: Bien, estás en C, por lo que no tienes espacios de nombres, y parece que quieres hacer referencia a ambas definiciones en la misma unidad de compilación. Pasos siguientes:

  • ¿Tienen exactamente la misma definición?
  • ¿Tiene alguna influencia sobre los nombres en cualquiera de las bibliotecas?
  • ¿Estás seguro de que no puedes ocultar referencias a uno de ellos en una unidad de compilación diferente?
+0

Las definiciones son idénticas. – pic11

+4

@pic: si las definiciones son idénticas, entonces no debería haber ningún problema. –

+0

@Oli. Sí, no hay problema, siempre y cuando las definiciones de dos libs no estén incluidas en la misma unidad de traducción. – pic11

4

Ni el enum sí, ni las constantes de enumeración son objetos, por lo que no tienen ningún vínculo en absoluto - en este sentido, son como struct etiquetas o nombres typedef.

Esto significa que tiene dos soluciones:

  • garantizar que los encabezados en conflicto no son nunca, directa o indirectamente, #include d en la misma unidad de traducción (.c archivo); o
  • Lavar uno o ambos encabezados para cambiar los nombres conflictivos.

El lavado de encabezado se puede hacer creando una copia privada del encabezado con los nombres modificados, o usando el preprocesador como en Chris Lutz's answer.

+0

+1. Cita: * Asegúrese de que los encabezados en conflicto nunca, directa o indirectamente, #incluidos en la misma unidad de traducción * – pic11

0

Cita: Estoy escribiendo C++ API y la misma enumeración ya está definida en el espacio de nombres de mi lib.

Entonces, ¿una de estas enumeraciones está dentro del espacio de nombres de su biblioteca? Entonces no deberías tener un problema. La biblioteca C que está utilizando se encuentra en el espacio de nombres global, su biblioteca tiene su propio espacio de nombres, y siempre que haga lo correcto, los dos nunca colisionarán. Lo siguiente es perfectamente válido, creo:

extern "C" { 
    #include "foo.h" 
    // enum Month { January, February, December }; 
} 

namespace mylib { 
    enum Month { Chaos, Discord, Confusion, Bureaucracy, Aftermath }; 

    Month convert(::Month c_month); 
} 

void foo() { 
    ::Month month = December; 
    mylib::Month result = mylib::convert(month); 
}