Home > Net >  Convert uint64_t to int64_t generically for all data widths
Convert uint64_t to int64_t generically for all data widths

Time:11-22

How does one generically convert signed and unsigned integers into each other without having to specify the specific width?

For example:

uint8_t <-> int8_t
uint16_t <-> int16_t
uint32_t <-> int32_t
uint64_t <-> int64_t

It would be nice to write:

uint32_t x;
int32_t y;
static_cast<signed>(x)
static_cast<unsigned>(y)

However, I suspect that doesn't do what I want.

I think I can achieve a similar effect using this method but I would think doing it for the same data width might have some syntactic sugar.

Conditional template type math

CodePudding user response:

However, I suspect that doesn't do what I want.

Indeed, your suspicion is valid: the expression, static_cast<signed>(x), is exactly equivalent to static_cast<signed int>(x), so the cast will always be to an object of the 'default' size of an int on the given platform (and, similarly, unsigned is equivalent to unsigned int).


However, with a little bit of work, you can create 'generic' cast template functions that use the std::make_signed and std::make_unsigned type-trait structures.

Here's a possible implementation of such functions, with a brief test program that shows some deduced result types for different input type widths:

#include <type_traits> // For make_signed and make_unsigned

template<typename T>
static inline auto unsigned_cast(T s)
{
    return static_cast<std::make_unsigned<T>::type>(s);
}

template<typename T>
static inline auto signed_cast(T s)
{
    return static_cast<std::make_signed<T>::type>(s);
}


#include <typeinfo>    // For "typeid"
#include <iostream>    

int main()
{
    int16_t s16 = 42;
    auto u16 = unsigned_cast(s16);
    std::cout << "Type of unsigned cast is: " << typeid(u16).name() << "\n";

    uint64_t u64 = 39uLL;
    auto s64 = signed_cast(u64);
    std::cout << "Type of signed cast is: " << typeid(s64).name() << "\n";
    return 0;
}
  •  Tags:  
  • c
  • Related