'Why is int -> size_t a narrowing conversion?

Consider this code:

#include <cstddef>
#include <cstdint>

int main()
{
    uint16_t z{1};
    uint16_t x{2};
    size_t y{x << z};

    return (int)y;
}

This code produces messages on GCC, Clang, and MSVC saying that size_t y{x << z} is a narrowing conversion. (A warning on GCC, an error on the other two).

According to GCC's warning message, x and z are being promoted to int. OK that makes some sense.

What I don't understand is how a conversion from int to size_t is a "narrowing" conversion, since size_t is larger than int.

Interestingly, to me at least, is that if I change the definition of x to uint32_t x{2}, the code compiles without issue.

c++


Solution 1:[1]

Though both int and size_t may be the same bit-wdth they differ in that the int is a signed value, so it's range (for, e.g. 16-bit) would be [-32768..+32767] while the same hypothetical 16-bit size_t would be in [0..65535] range. That conversion from a signed value to an unsigned is what is being reported as "narrowing".

A fix (in this case) is based on knowledge that your values are indeed unsigned so you can "tell" the compiler as much with an explicit conversion:

auto y{static_cast<size_t>(x << z)};

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1