ПРИМЕЧАНИЕ: Я добавил аналогичную, но значительно упрощенную версию проблемы в Неоднозначная перегрузка функций, таких как `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_t
etc не 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_
на основе количества битов в целочисленном типе.
Я помещаю два предлагаемых решения, поскольку ни одно из лучших решений не попало в начало списка, а есть несколько неработающих.
Предоставлено Cheers and hth. - Альф.Комментарии с этого момента являются моими собственными - не стесняйтесь комментировать и/или редактировать.
Преимущества
- Довольно просто (по крайней мере по сравнению с boost::enable_if
)
- Не полагается на стороннюю библиотеку (пока компилятор поддерживает tr1
)
*Недостатки**
- Если требуется больше функций (например, AnotherObj_from_int32
и т. д.), потребуется намного больше кода.
Это решение можно найти ниже — взгляните, оно отлично!
Преимущества
Как только функции 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)`