Determinar o número de bits no tipo integral em tempo de compilação

NOTA: Eu adicionei uma versão semelhante mas muito simplificada do problema emSobrecarga ambígua de funções como `msg (long)` com candidatos `msg (int32_t)` e `msg (int64_t)`. Essa versão tem a vantagem de um exemplo compilável completo em um único arquivo.

Problema

Eu tenho uma biblioteca C com funções 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>

Neste caso, os tiposint32_t etc sãonão astd ones - são implementação definida, neste caso uma matriz de chars (no exemplo a seguir omiti a conversão - ela não altera a questão que é sobre o mapeamento de tipos intergral para uma função específica baseada no número de bits em o tipo integral).

Eu tenho uma segunda classe de interface C ++, que tem construtores 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>

Note que não posso substituir esta interface porstd::int32_t tipos de estilo - se eu pudesse, não precisaria fazer essa pergunta;)

O problema é como chamar o corretoobj_from_ função baseada no número de bits no tipo integral.

Soluções propostas

Estou colocando duas soluções propostas, já que nenhuma solução matadora chegou ao topo da lista, e há algumas que estão quebradas.

Solução 1

Fornecido porCheers e hth. - Alf. Comentários deste ponto em diante são meus - sinta-se livre para comentar e / ou editar.

Vantagens - Razoavelmente simples (pelo menos em comparação comboost::enable_if) - Não depende da biblioteca de terceiros (desde que o compilador suportetr1)

* Desvantagens ** - Se mais funções (comoanotherObj_from_int32 etc) são necessários, muito mais código é necessário

Esta solução pode ser encontrada abaixo - dê uma olhada, é bacana!

Solução 2

Vantagens

Uma vez oConvertFromIntegral funções são feitas, adicionando novas funções que precisam da conversão é trivial - basta escrever um conjunto sobrecarregado emint32_t, int64_t e equivalentes não assinados.

Mantém o uso de modelos em um único local, eles não se espalham à medida que a técnica é reutilizada.

Desvantagens

Pode ser excessivamente complicado, usandoboost::enable_if. Algo atenuado pelo fato de isso aparecer em apenas um lugar.

Como isso é meu, não posso aceitá-lo, mas você pode fazer o upvote se achar que é legal (e claramente algumas pessoas o fazem).não acho que é legal em tudo, é para isso que eu acho que é downvote!) Obrigado a todos que contribuíram com ideias!

A solução envolve uma função de conversãoint, long elong long paraint32_t eint64_t (e similar para as versões não assinadas). Isso é combinado com outro conjunto de funções sobrecarregadasint32_t, int64_t e equivalentes não assinados. As duas funções podem ser combinadas, mas as primeiras funções de conversão tornam um útil conjunto de utilitários que pode ser reutilizado e, em seguida, o segundo conjunto de funções é trivialmente simples.

<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>

Um simplificado (único compilável.cpp!) versão da solução é dada emSobrecarga ambígua de funções como `msg (long)` com candidatos `msg (int32_t)` e `msg (int64_t)`

questionAnswers(5)

yourAnswerToTheQuestion