c++ - programacion - principales librerias en lenguaje c
Proporcionar una API de C a su biblioteca de C++ y un alias estricto (1)
No es una violación estricta aliasing. Para empezar, el aliasing estricto consiste en acceder a un objeto a través de un glvalue del tipo incorrecto.
En su pregunta, crea un LLVMContext
y luego utiliza un valor de LLVMContext
para acceder a él. No hay alias ilegal allí.
El único problema que puede surgir es si la conversión del puntero no devuelve el mismo puntero. Pero eso tampoco es un problema, ya que se garantiza que reinterpret_cast
devolverá el mismo puntero en una conversión de ida y vuelta. Siempre que el tipo de puntero al que convertimos y retrocedamos sea a datos adecuadamente alineados (es decir, no más estrictos que el tipo original).
Es discutible si es una buena o mala manera de hacer las cosas. Personalmente no me molestaría en LLVMOpaqueContext
y devolvería una struct LLVMContext*
. Sigue siendo un puntero opaco, y no importa que el encabezado C lo declare con struct
mientras que la definición de tipo sea con class
. Los dos son intercambiables hasta el punto de la definición de tipo.
Un patrón común cuando se proporciona una API de C es reenviar y declarar algunos tipos opacos en su encabezado público que se pasan a sus métodos de API y luego reinterpret_cast
en sus tipos de C ++ definidos una vez dentro de la unidad de traducción (y por lo tanto nuevamente en C ++).
Usando LLVM como ejemplo:
En Types.h se declara este typedef:
typedef struct LLVMOpaqueContext *LLVMContextRef;
LLVMOpaqueContext
se hace referencia a LLVMOpaqueContext
ningún otro lugar del proyecto.
En Core.h el siguiente método:
LLVMContextRef LLVMContextCreate(void);
Que se define en Core.cpp :
LLVMContextRef LLVMContextCreate() {
return wrap(new LLVMContext());
}
wrap
(y unwrap
) está definido por una macro en CBindingWrapping.h :
#define DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) /
inline ty *unwrap(ref P) { /
return reinterpret_cast<ty*>(P); /
} /
/
inline ref wrap(const ty *P) { /
return reinterpret_cast<ref>(const_cast<ty*>(P)); /
}
Y usado en LLVMContext.h :
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMContext, LLVMContextRef)
Así que vemos que la API de C básicamente lleva un puntero a LLVMOpaqueContext
y lo convierte en un objeto llvm::LLVMContext
para realizar cualquier método que se llame en él.
Mi pregunta es: ¿no viola esto las estrictas reglas de alias? ¿Si no, porque no? Y si es así, ¿cómo puede lograrse legalmente este tipo de abstracción en el límite de la interfaz pública?