Stroustrup states in C++ Programming Language 4th edition page 271 that the result of converting an unsigned integer to a signed one of possibly larger size implementation defined. This contradicts him saying that the value is unchanged if it can be represented in the destination type, otherwise it is implementation defined
What is this mess?
If an unsigned value is assigned to a signed variable of larger size it will always fit, so what is the problem?
converting an unsigned integer to a signed one of possibly larger size implementation defined.
There is no contradiction. The important word here is "possibly". I.e., whether a long is larger than an int or whether a long long is larger than a long is implementation defined. So whether the result is signed or unsigned is implementation defined. Messy stuff. That's why you should avoid mixing signed and unsigned.
1 2 3
unsigned n;
long m;
m + n // implementation defined whether this is long or unsigned long
That's an unexploded bomb that could explode at any time! Proceed with extreme caution. Note that a number such as 1 is deemed to be signed. If you want an unsigned number then you need to use integer literal U (eg 1U). See: https://en.cppreference.com/w/cpp/language/integer_literal
this is one of the reasons I try to avoid size-changing types like 'long' which is often just 'int' in size. If you used int64_t or int32_t the 'possibly' part goes away for your code, at the risk of bumping into platforms that don't have a 64 bit integer capacity -- they do still exist.
generally its 'bad' to mix signed/unsigned and its also 'bad' to try to do logic ops on signed. That is really what you need to know, is to do your best to avoid the issue entirely, rather than trying to work within the extremely aggravating rules that crop up when you don't avoid it. Code that mixes signs is one of those things like the pentium hardware bug... it works so much of the time that when it finally breaks, finding the problem, reproducing it, etc becomes very difficult.
This is one of the reasons why .ssize()/std::ssize was introduced to give a signed result instead of the unsigned .size()/std::size. Note that size_t is the unsigned type and ptrdiff_t is the signed type. Don't use int!