Определить количество бит в целочисленном типе во время компиляции
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_
Функция основана на количестве бит в целочисленном типе.
Я предлагаю два предлагаемых решения, поскольку ни одно убийственное решение не попало в верхнюю часть списка, а некоторые из них не работают.
Solution 1ПредоставленоУра и hth. Альф, Комментарии с этого момента являются моими собственными - не стесняйтесь комментировать и / или редактировать.
Advantages
- Довольно просто (по крайней мере, по сравнению сboost::enable_if
)
- Doesn't rely on 3rd party library (as long as compiler supports tr1
)
* Недостатки **
- Если больше функций (например,anotherObj_from_int32
и т. д.), требуется гораздо больше кода
Это решение может быть найдено ниже - посмотрите, это изящно!
Solution 2Advantages
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, usingboost::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)`