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

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

Проблема

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

obj_from_int32(int32_t& i);
obj_from_int64(int64_t& i);
obj_from_uint32(uint32_t& i);
obj_from_uint64(uint64_t& i);

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

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

MyClass(int z);
MyClass(long z);
MyClass(long long z);
MyClass(unsigned int z);
MyClass(unsigned long z);
MyClass(unsigned long long z);

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

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

Предлагаемые решения

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

Решение 1

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

Преимущества - Довольно просто (по крайней мере по сравнению с boost::enable_if) - Не полагается на стороннюю библиотеку (пока компилятор поддерживает tr1)

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

Это решение можно найти ниже — взгляните, оно отлично!

Решение 2

Преимущества

  • Как только функции ConvertFromIntegralвыполнены, добавление новых функций, требующих преобразования, тривиально — просто напишите набор, перегруженный на int32_t, int64_tи беззнаковые эквиваленты.

  • Сохраняет использование шаблонов только в одном месте, они не распространяются, так как техника используется повторно.

Недостатки

  • Может быть слишком сложным при использовании boost::enable_if. Несколько смягчается тем фактом, что это появляется только в одном месте.

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

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

// Utility conversion functions (reuse wherever needed)
template 
typename boost::enable_if_c::value,
 int32_t>::type ConvertFromIntegral(InputT z) { return static_cast(z); }

template 
typename boost::enable_if_c::value, 
int64_t>::type ConvertFromIntegral(InputT z) { return static_cast(z); }

template 
typename boost::enable_if_c::value, 
uint32_t>::type ConvertFromIntegral(InputT z) { return static_cast(z); }

template 
typename boost::enable_if_c::value, 
uint64_t>::type ConvertFromIntegral(InputT z) { return static_cast(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))) {}

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

7
задан Community 23 May 2017 в 12:11
поделиться