1

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"?

FlashMcQueen
  • 635
  • 3
  • 13

3 Answers3

4

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.

The Quantum Physicist
  • 24,987
  • 19
  • 103
  • 189
2

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).

op414
  • 582
  • 5
  • 15
  • 2
    actually... you kind of can make this assumption https://en.cppreference.com/w/cpp/language/types The committee finally accepted that two's complement is the only used representation and the proposal to require two's complement has been accepted into C++20 https://herbsutter.com/2018/11/13/trip-report-fall-iso-c-standards-meeting-san-diego/ – bolov Nov 27 '18 at 10:17
1

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));
}
Matthieu Brucher
  • 21,634
  • 7
  • 38
  • 62