1
votes

If the destination type is signed, the value does not change if the source integer can be represented in the destination type.

If I understand well, is it guaranteed that :

static_cast<std::int8_t>(static_cast<std::int16_t>(-3)) == -3

?

Because -3 can be represented in an std::int8_t.

Thus in the example of a two s complement:

Then in the example of the two's complement function, do I need an intermediaite cast to std::uintmax_t?

#include <type_traits>

template <typename T>
T twos_complement(T val)
{
    typedef std::make_unsigned<T>::type U;

    return static_cast<T>(-static_cast<uintmax_t>(static_cast<U>(val)));
}

because

return static_cast<T>(-static_cast<U>(val));

integral promotion applied before unary minus could "ruin the effect of casting to an unsigned type if T is narrower than int"?

3
What are you trying to do?Matthieu Brucher
Writting a two's complement function by using only necessary casts.FlashMcQueen
What's your question exactly? What do you need help with?The Quantum Physicist
First: is the value -3 preserved after casting to narrower signed? Second is it necessary in the example of the two's complement to protect against a potential integral promotion in case T is narrower than int .FlashMcQueen
It is preserved if it fits into smaller type. So -3 is fine. But -1000 is not in your example.Anty

3 Answers

4
votes

Why don't you get the two's complement like this:

uint32_t num = 10;
uint32_t cmp = ~num + 1; // this is two's complement of 10.

Doesn't this work for you?

EDIT: if you're worried that an overflow may occur (for either signed or unsigned), just do this first:

if(~num == std::numeric_limits<MyIntType>::max()) {
    // overflow mitigation
}

You can also statically check whether your type is signed or unsigned to mitigate overflow problems in appropriate ways with std::is_signed and std::is_unsigned.

2
votes

Signed/Unsigned representations are platform-dependent. Even if most modern platforms use the two's complement to represent signed numbers, you can not make this assumption. Using static_cast to perform a two's complement is not the right way to go. If you want to do bit manipulation yourself, use fixed-size unsigned types as in The Quantum Physicist's answer (but note that again, what will happen in case of overflow on the addition is platform dependent).

1
votes

Adapting the code that you linked with C++ casts:

#include <cstdint>

template <typename T>
T twos_complement(T val)
{
    return static_cast<T>(-static_cast<uintmax_t>(val));
}