从和构造C++整型< number of bytes>< signedness>

5lwkijsr  于 2023-05-20  发布在  其他
关注(0)|答案(3)|浏览(105)
  • 我有一个constexpr size_t byte_count,它可以是1、2、4或8
  • 我有一个constexpr bool is_signed,它显然不是真就是假

我想用sizeof(T) == byte_countstd::is_signed_v<T> == is_signed为整数类型T构造一个typedef/using

  1. <type_traits>(或标准库中的其他地方)中是否有这样做的东西?
    1.否则,实现这一点的最紧凑的方法是什么?
  • 我真的很喜欢一些简短的东西,不硬编码的类型,因为这将在多个地方使用,它是恼人的介绍助手函数/类型(它的内部生成的代码…叹气)。
  • 我没有助推器。

我目前的解决方案:

#include <type_traits>
#include <tuple>
#include <cstddef>
#include <cstdint>

int main(){
    constexpr size_t byte_count = 4; // either 1, 2, 4, or 8
    constexpr bool is_signed = true; // either true or false

    // I would like to have something shorter and less hardcoded than this
    using T = std::conditional_t<
        is_signed,
        std::tuple_element_t<byte_count, std::tuple<int8_t, int16_t, int16_t, int32_t, int32_t, int32_t, int32_t, int64_t>>,
        std::tuple_element_t<byte_count, std::tuple<uint8_t, uint16_t, uint16_t, uint32_t, uint32_t, uint32_t, uint32_t, uint64_t>>
    >;

    static_assert(sizeof(T) == byte_count);
    static_assert(std::is_signed_v<T> == is_signed);
}
xn1cxnb4

xn1cxnb41#

C++标准库中没有任何东西可以做到这一点。不幸的是,您必须自己实现Map。
您可以使用std::make_signed_t来删除一半的案例。
就像这样:

template<std::size_t ByteWidth>
struct select_uint;

template<> struct select_uint<1> { using type = std::uint8_t; };
template<> struct select_uint<2> { using type = std::uint16_t; };
template<> struct select_uint<4> { using type = std::uint32_t; };
template<> struct select_uint<8> { using type = std::uint64_t; };

template<std::size_t ByteWidth, bool IsSigned>
using select_int_t = std::conditional_t<IsSigned,
    std::make_signed_t<typename select_uint<ByteWidth>::type>,
    typename select_uint<ByteWidth>::type>;
6fe3ivhb

6fe3ivhb2#

您将不得不列出类型,但您可以使用helper函数使其更容易完成。看起来像是

template <std::size_t bytes, bool is_signed>
auto int_type()
{
    if constexpr (bytes == 1 && is_signed)       return int8_t{};
    else if constexpr (bytes == 1)               return uint8_t{};
    else if constexpr (bytes == 2 && is_signed)  return int16_t{};
    else if constexpr (bytes == 2)               return uint16_t{};
    else if constexpr (bytes == 4 && is_signed)  return int32_t{};
    else if constexpr (bytes == 4)               return uint32_t{};
    else if constexpr (bytes == 8 && is_signed)  return int64_t{};
    else if constexpr (bytes == 8)               return uint64_t{};
    else                                         return; // void for the error case
}

template <std::size_t bytes, bool is_signed>
using int_type_t = decltype(int_type<bytes, is_signed>());

int main()
{
    int_type_t<1, true> b = 1;
}
whlutmcx

whlutmcx3#

我认为没有什么比显式列出所有类型更好的了。
这可能类似于:

template <int size, bool is_signed>
struct int_traits;

template <>
struct int_traits<1, false> { using type = uint8_t; };
template <>
struct int_traits<1, true> { using type = int8_t; };
template <>
struct int_traits<2, false> { using type = uint16_t; };
template <>
struct int_traits<2, true> { using type = int16_t; };

template <int size, bool is_signed>
using int_t = typename int_traits<size, is_signed>::type;

int main()
{
    int_t<1, true> b = 1;
}

相关问题