Разрешение перегрузки шаблона функции

Я хотел написать несколько шаблонных функций для обработки типов определенным образом, поэтому я пришел к этим двум функциям. Первый берет объект и преобразует его со штамповкой в ​​другой. Это гарантирует, что оба типа являются POD и имеют одинаковый размер. Второй был предназначен для того, чтобы просто взять любой указатель (как если бы void *), но все равно проверять, чтобы убедиться, что указатель относится к типу POD. Проблема, с которой я столкнулся, заключается в том, что если я передам неконстантный указатель, то вместо этого будет использоваться первая функция. Что было бы лучшим способом справиться с этим?

template <class TO, class FROM>
FORCE_INLINE TO punning_cast(const FROM &input)
{
static_assert(std::is_pod<TO>::value, "TO must be POD");
static_assert(std::is_pod<FROM>::value, "FROM must be POD");
static_assert(sizeof(TO) == sizeof(FROM), "TO and FROM must be the same size");

TO out;
std::memcpy(&out, &input, sizeof(TO));
return out;
}

template <class TO, class FROM>
FORCE_INLINE TO punning_cast(const FROM *input)
{
static_assert(std::is_pod<TO>::value, "TO must be POD");
static_assert(std::is_pod<FROM>::value, "FROM must be POD");

TO out;
std::memcpy(&out, input, sizeof(TO));
return out;
}

2

Решение

Шаблоны функций смешивать странно с перегрузкой.

Возможное решение (не уникальное) будет использовать enable_if для объявления каждой функции, кодирующей вторую для типов указателей, и наоборот для первой

#include <type_traits>

template <class TO, class FROM>
FORCE_INLINE typename enable_if<!is_pointer<FROM>::value, TO>::type
punning_cast(const FROM &input) { ... }

template <class TO, class FROM>
FORCE_INLINE typename enable_if<is_pointer<FROM>::value, TO>::type
punning_cast(const FROM input) { ... }

Таким образом, примером достижения устранения неоднозначности (между ссылкой и указателем) будет этот

3

Другие решения

Отказ от ответственности: мне нравится Никос Атанасиу ответ лучше для C ++ 11 и далее.

Одним из решений этой (общей) проблемы является обертывание функций в структуры и добавление вспомогательной функции, которая выбирает одну из них:

template <class TO, class FROM>
struct punning_cast_impl
{
static FORCE_INLINE TO cast(const FROM &input)
{
static_assert(std::is_pod<TO>::value, "TO must be POD");
static_assert(std::is_pod<FROM>::value, "FROM must be POD");
static_assert(sizeof(TO) == sizeof(FROM), "TO and FROM must be the same size");

TO out;
std::memcpy(&out, &input, sizeof(TO));
return out;
}
};

template <class TO, class FROM>
struct punning_cast_impl<TO, FROM*>
{
static FORCE_INLINE TO cast(const FROM *input)
{
static_assert(std::is_pod<TO>::value, "TO must be POD");
static_assert(std::is_pod<FROM>::value, "FROM must be POD");

TO out;
std::memcpy(&out, input, sizeof(TO));
return out;
}
};

template<class TO, class FROM>
TO FORCE_INLINE punning_cast(const FROM& input)
{
return punning_cast_impl<TO, FROM>::cast(input);
}

int main()
{
double d1 = 50.0;
int64_t i1 = punning_cast<int64_t>(d1); // calls version #1

double d2 = 100.0;
int64_t i2 = punning_cast<int64_t>(&d2); // calls version #2
}
3

По вопросам рекламы [email protected]