Определить количество бит в целочисленном типе во время компиляции

NOTE: Я добавил похожую, но значительно упрощенную версию проблемы вНеоднозначная перегрузка функций типа `msg (long)` с кандидатами `msg (int32_t)` и `msg (int64_t)`, Эта версия имеет преимущество полного скомпилированного примера в одном файле.

Problem

У меня есть библиотека C с функциями, такими как

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

В этом случае типыint32_t и т. д.not std единицы - они определены реализацией, в данном случае - массивом символов (в следующем примере преобразование я пропустил - это не меняет вопрос о сопоставлении типов интегралов с конкретной функцией на основе количества битов в интегральный тип).

У меня есть второй интерфейс класса C ++, который имеет конструкторы, такие как

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

Обратите внимание, я не могу заменить этот интерфейсstd::int32_t типы стилей - если бы я мог, мне бы не пришлось задавать этот вопрос;)

Проблема в том, как правильно назватьobj_from_ Функция основана на количестве бит в целочисленном типе.

Proposed Solutions

Я предлагаю два предлагаемых решения, поскольку ни одно убийственное решение не попало в верхнюю часть списка, а некоторые из них не работают.

Solution 1

ПредоставленоУра и hth. Альф, Комментарии с этого момента являются моими собственными - не стесняйтесь комментировать и / или редактировать.

Advantages  - Довольно просто (по крайней мере, по сравнению сboost::enable_if) - Doesn't rely on 3rd party library (as long as compiler supports tr1)

* Недостатки **  - Если больше функций (например,anotherObj_from_int32 и т. д.), требуется гораздо больше кода

Это решение может быть найдено ниже - посмотрите, это изящно!

Solution 2

Advantages

Once the ConvertFromIntegral functions are done, adding new functions that need the conversion is trivial - simply write a set overloaded on int32_t, int64_t and unsigned equivalents.

Keeps use of templates to one place only, they don't spread as the technique is reused.

Disadvantages

Might be overly complicated, using boost::enable_if. Somewhat mitigated by the fact this appears in once place only.

Поскольку это мое собственное, я не могу принять это, но вы можете выразить это, если считаете, что это аккуратно (и, очевидно, некоторые людиnot я думаю, что это аккуратно, вот почему я думаю об этом, я думаю!) Спасибо всем, кто поделился идеями!

Решение включает в себя функцию преобразования изint, long а такжеlong long вint32_t а такжеint64_t (и аналогично для неподписанных версий). Это в сочетании с другим набором функций, перегруженных наint32_t, int64_t и беззнаковые эквиваленты. Эти две функции могут быть объединены, но первые функции преобразования образуют удобный набор утилит, который можно использовать повторно, а затем второй набор функций тривиально прост.

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

Упрощенный (один компилируемый.cpp!) версия решения дана наНеоднозначная перегрузка функций типа `msg (long)` с кандидатами `msg (int32_t)` и `msg (int64_t)`

Ответы на вопрос(5)

Ваш ответ на вопрос