提问人:ChrisB 提问时间:5/12/2023 最后编辑:ChrisB 更新时间:5/12/2023 访问量:133
从<字节数>和<符号性构造C++整数类型>
Construct C++ Integer type from <number of bytes> and <signedness>
问:
- 我有一个 ,它是 1、2、4 或 8
constexpr size_t byte_count
- 我有一个 ,它显然是真的或假的
constexpr bool is_signed
我想用 和 为 Integer 类型构造一个 /。typedef
using
T
sizeof(T) == byte_count
std::is_signed_v<T> == is_signed
(或标准库中的其他地方)中是否有东西可以做到这一点?
<type_traits>
否则,实现此目的的最紧凑方法是什么?
我真的想要一些简短的东西,它不会对类型进行硬编码,因为这将在多个地方使用,在这些地方引入帮助程序函数/类型很烦人(它在生成的代码中......唉)。
我没有提升。
我目前的解决方案:
#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);
}
答:
2赞
Alan Birtles
5/12/2023
#1
我认为没有比明确列出所有类型更好的了。
这可能看起来像这样:
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;
}
评论
0赞
Remy Lebeau
5/12/2023
该语句需要使用,因为它对依赖于模板参数的类型进行别名化,例如:请参阅 stackoverflow.com/questions/610245using
typename
using int_t = typename int_traits<size, is_signed>::type;
7赞
Artyer
5/12/2023
#2
C++ 标准库中没有任何内容可以执行此操作。不幸的是,您必须自己实现映射。
您可以使用 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>;
2赞
NathanOliver
5/12/2023
#3
你将不得不列出类型,但你可以使用帮助程序函数来简化操作。这可能看起来像
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;
}
评论
<cstdint>