Let's consider the function (one of possible implementations of it) which would zero out right N bits of an unsigned short value (or any other unsigned integral type). The possible implementation could look like following:
template<unsigned int shift>
unsigned short zero_right(unsigned short arg) {
using type = unsigned short;
constexpr type mask = ~(type(0));
constexpr type right_zeros = mask << shift; // <-- error here
return arg & right_zeros;
}
int check() {
return zero_right<4>(16);
}
With this code, all compilers I have access to complain, in one way or another, about possible overflow. CLang is the most explicit one, with following clear message:
error: implicit conversion from 'int' to 'const type' (aka 'const unsigned short') changes value from 1048560 to 65520 [-Werror,-Wconstant-conversion]
This code looks well defined and clear as day to me, yet when 3 compilers complain, I am becoming very nervous. Am I missing something here? Is there really a chance something fishy is happening?
P.S. While alternative implementations of zeriong out left X bits might be welcome and interesting, the primary focus of this question is of validity of code as posted.