Преобразовать параметр шаблона интегрального типа C ++ в «более длинный» целочисленный тип - PullRequest
0 голосов
/ 29 января 2019

У меня есть шаблонная функция, которая принимает целочисленный тип и выполняет математическую операцию с двумя входными параметрами:

template<typename T, typename R>
R multiply( const T& lhs, const T& rhs ) {
  R ans = static_cast<R>( lhs ) * static_cast<R>( rhs );
  return ans;
}

(Для простоты предположим, что типы T и R всегда являются целыми типами без знака, или чтоЯ выполняю подходящую проверку, чтобы убедиться.)

В этом надуманном примере вы можете видеть, что я делаю простое умножение (только для иллюстрации).Идея состоит в том, чтобы передать тип R, ширина которого вдвое больше, чем у типа T;это позволит всему продукту вписаться в возвращаемое значение:

uint64_t Product64 = multiply<uint32_t,uint64_t>( 0xFFFFFFFF, 0xFFFFFFFF );
uint16_t Product16 = multiply<uint8_t,uint16_t>( 0xFF, 0xFF );

Мне интересно, есть ли любой способ обойтись без второго параметра шаблона автоматически вычисляет тип, ширина которого [по меньшей мере] вдвое больше, чем у типа T, в время компиляции .

Примечание. Просто используйтеНаибольший доступный целочисленный тип (uint64_t) для R во все времена не является решением для меня.В идеале я хочу, чтобы тип, вычисляемый во время компиляции, был достаточно большим , чтобы содержать вдвое больше битов, чем тип T (например, когда T = uint8_t, R = uint16_t).

Мне кажется, это должно быть возможно с помощью limit или type_traits или чего-то подобного, но пока я не думал о решении.C ++ 11 или более поздняя версия в порядке.Я бы предпочел избегать повышения, но если это единственный способ, мне было бы интересно также увидеть решение на основе повышения.

1 Ответ

0 голосов
/ 29 января 2019

Вы можете создать свои собственные типы шаблонных размеров и использовать их для определения типа возвращаемого значения, как показано ниже:

#include <cstdint>
template<int N>
struct sized_uint {};
template<> struct sized_uint<8 > { using type=std::uint8_t; };
template<> struct sized_uint<16> { using type=std::uint16_t; };
template<> struct sized_uint<32> { using type=std::uint32_t; };
template<> struct sized_uint<64> { using type=std::uint64_t; };

#include <climits>
template<typename T>
auto multiply(T lhs, T rhs)
{
  using R=typename sized_uint<CHAR_BIT*sizeof(T)*2>::type;
  return static_cast<R>(static_cast<R>(lhs) * static_cast<R>(rhs));
}

Посмотреть вживую.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...