constexpr size_t byte_count
, which is either 1, 2, 4, or 8constexpr bool is_signed
, which is obviously either true or falseI want to construct a typedef
/using
for an Integer type T
with sizeof(T) == byte_count
and std::is_signed_v<T> == is_signed
.
Is there something in <type_traits>
(or elsewhere in the standard library) that does this?
Otherwise, what is the most compact way to achieve this?
I'd really like something short that does not hardcode the types since this will be used in multiple places where it's annoying to introduce helper functions/types (it's inside of generated code... sigh).
I don't have boost.
My current solution:
#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);
}
There is nothing in the C++ standard library that will do this. Unfortunately, you will have to implement the mapping yourself.
You can use std::make_signed_t
to get rid of half of the cases.
Something like this:
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>;