He tenido el mismo problema en el pasado, y así es como lo he solucionado. Quería poder cambiar la implementación de una biblioteca en tiempo de compilación. Uno de los lib estaba usando código como este:
namespace Lib1
{
enum LibEnum { One, Two, Three };
[...]
void someFunc(LibEnum val);
}
En mi código, quería ocultar la implementación de la biblioteca de la experiencia del usuario (lo que un usuario de mi código nunca debe ver lo lib estoy usando internamente):
Solución 1:
namespace MyCode
{
// Example to avoid copying a function from Lib1 here
typedef Lib1::someFunc aFunctionImUsing;
// This doesn't work
// typedef LibEnum MyEnum;
// As such code doesn't compile:
// aFunctionImUsing(One); // Error unknown identifier One
// But this did:
struct Type
{
enum MyType { One = Lib1::One, Two = Lib1::Two, Three = Lib1::Three };
}
static inline Lib1::LibEnum as(Type::MyType t) { return (Lib1::LibEnum)t; }
// Now code like this compiles:
aFunctionImUsing(as(Type::One));
// This one doesn't:
// aFunctionImUsing(Type::One); // Can't convert from Type::MyType to Lib1::LibEnum
[...]
}
Solución 2:
namespace MyCode
{
struct Type
{
enum MyType { One = Lib1::One, Two = Lib1::Two, Three = Lib1::Three };
}
// If you don't care about polluting your namespace with numerous wrapper
// you can write this instead of typedef someFunc:
static inline void myFunc(Type::MyType t) { return Lib1::someFunc((Lib1::LibEnum)t); }
// This one does:
myFunc(Type::One);
[...]
}
Son 2 problemas con el fragmento de código anterior.El primer problema es que debe copiar & pegue la enumeración dentro de su espacio de nombres, (pero con una expresión regular simple en find & replace, ya está). El segundo problema es que su usuario tendrá que usar el método "como", lo que significa que no es sencillo, o tiene que ajustar el método/función con la segunda solución.
De todos modos, como no es posible inyectar una enumeración en el espacio de nombre, esta solución es lo mejor que puede hacer. Tenga en cuenta que su usuario de código ni siquiera sabe que está utilizando la biblioteca Lib1 en el código de ejemplo.
"Específicamente, no quiero decir A :: E1", ¿por qué no? –
porque A se usa en varias clases y no quiero referirme a un tipo no relacionado. En mi uso real, A es un tipo anidado que es typedefed en otro lugar, y realmente sería más como N :: E :: C :: A :: E1 – rlbond
Luego tendrá que hacer un espacio de nombre y definir la enumeración ahí. ¿Por qué no haces eso? –