Determine el número de bits en tipo integral en el momento de la compilación

NOTA: Agregué una versión similar pero muy simplificada del problema enSobrecarga ambigua de funciones como `msg (long)` con candidatos `msg (int32_t)` y `msg (int64_t)`. Esa versión tiene la ventaja de un ejemplo compilable completo en un solo archivo.

Problema

Tengo una biblioteca de C con funciones como

<code>obj_from_int32(int32_t& i);
obj_from_int64(int64_t& i);
obj_from_uint32(uint32_t& i);
obj_from_uint64(uint64_t& i);
</code>

En este caso los tipos.int32_t etc sonno lastd unos - se definen por implementación, en este caso una matriz de caracteres (en el siguiente ejemplo, omití la conversión), no cambia la pregunta que trata sobre la asignación de tipos intergral a una función particular en función del número de bits en el tipo integral).

Tengo una segunda clase de interfaz C ++, que tiene constructores como

<code>MyClass(int z);
MyClass(long z);
MyClass(long long z);
MyClass(unsigned int z);
MyClass(unsigned long z);
MyClass(unsigned long long z);
</code>

Nota, no puedo reemplazar esta interfaz constd::int32_t tipos de estilo - si pudiera no necesitaría hacer esta pregunta;)

El problema es cómo llamar al correcto.obj_from_ Función basada en el número de bits en el tipo integral.

Soluciones propuestas

Estoy poniendo dos soluciones propuestas, ya que ninguna solución asesina ha flotado en la parte superior de la lista, y hay algunas que están rotas.

Solución 1

Proporcionado porSaludos y hth. - Alf. Los comentarios a partir de este momento son míos, no dude en comentar y / o editar.

Ventajas - Bastante simple (al menos en comparación conboost::enable_if) - No confía en la biblioteca de terceros (siempre que el compilador sea compatible contr1)

* Desventajas ** - Si hay más funciones (comoanotherObj_from_int32 etc) son necesarios, se requiere mucho más código

Esta solución se puede encontrar a continuación. ¡Echa un vistazo, es ingenioso!

Solucion 2

Ventajas

Una vez elConvertFromIntegral Las funciones se realizan, agregando nuevas funciones que requieren que la conversión sea trivial, simplemente escriba un conjunto sobrecargado enint32_t, int64_t y equivalentes sin firmar.

Mantiene el uso de plantillas solo en un lugar, no se propagan a medida que la técnica se reutiliza.

Desventajas

Podría ser demasiado complicado, usandoboost::enable_if. Algo mitigado por el hecho de que esto aparece en un solo lugar.

Ya que este es el mío, no lo puedo aceptar, pero puedes mejorarlo si crees que está limpio (y claramente algunas personas lo hacen).no Creo que está limpio, ¡para eso lo votamos!) ¡Gracias a todos los que contribuyeron con ideas!

La solución implica una función de conversión deint, long ylong long aint32_t yint64_t (y similar para las versiones sin firmar). Esto se combina con otro conjunto de funciones sobrecargadas enint32_t, int64_t y equivalentes sin firmar. Las dos funciones podrían combinarse, pero las primeras funciones de conversión constituyen un útil conjunto de utilidades que se pueden reutilizar, y luego el segundo conjunto de funciones es trivialmente simple.

<code>// Utility conversion functions (reuse wherever needed)
template <class InputT>
typename boost::enable_if_c<sizeof(InputT)==sizeof(int32_t) && boost::is_signed<InputT>::value,
 int32_t>::type ConvertFromIntegral(InputT z) { return static_cast<int32_t>(z); }

template <class InputT>
typename boost::enable_if_c<sizeof(InputT)==sizeof(int64_t) && boost::is_signed<InputT>::value, 
int64_t>::type ConvertFromIntegral(InputT z) { return static_cast<int64_t>(z); }

template <class InputT>
typename boost::enable_if_c<sizeof(InputT)==sizeof(uint32_t) && boost::is_unsigned<InputT>::value, 
uint32_t>::type ConvertFromIntegral(InputT z) { return static_cast<uint32_t>(z); }

template <class InputT>
typename boost::enable_if_c<sizeof(InputT)==sizeof(uint64_t) && boost::is_unsigned<InputT>::value, 
uint64_t>::type ConvertFromIntegral(InputT z) { return static_cast<uint64_t>(z); }

// Overload set (mock implementation, depends on required return type etc)
void* objFromInt32 (int32_t i)   { obj_from_int32(i); }
void* objFromInt64 (int64_t& i)  { obj_from_int64(i); }
void* objFromUInt32(uint32_t& i) { obj_from_uint32(i); }
void* objFromUInt64(uint64_t& i) { obj_from_uint64(i); }

// Interface Implementation
MyClass(int z) : _val(objFromInt(ConvertFromIntegral(z))) {}
MyClass(long z): _val(objFromInt(ConvertFromIntegral(z))) {}
MyClass(long long z): _val(objFromInt(ConvertFromIntegral(z))) {}
MyClass(unsigned int z): _val(objFromInt(ConvertFromIntegral(z))) {}
MyClass(unsigned long z): _val(objFromInt(ConvertFromIntegral(z))) {}
MyClass(unsigned long long z): _val(objFromInt(ConvertFromIntegral(z))) {}
</code>

Un simplificado (single compilable.cpp!) La versión de la solución se da enSobrecarga ambigua de funciones como `msg (long)` con candidatos `msg (int32_t)` y `msg (int64_t)`

Respuestas a la pregunta(5)

Su respuesta a la pregunta