When you add two integral values together, such that both values can fit within an int
, they are added as int
s.
If you require an unsigned int
to fit one of them, they are instead added as unsigned int
s.
If those are not big enough, bigger types can be used. It gets complicated, and it changes by standard revision if I remember rightly (there where some rough spots).
Now, addition with int
s is unspecified if it overflows. Addition with unsigned int
s is guaranteed to wrap mod some power of two.
When you convert an int
or an unsigned int
to a signed type, if it doesn't fit the result is unspecified. If it does fit, it fits.
If you convert an int
or unsigned int
to an unsigned type, the value that can be represented equal to the source mod some power of two (fixed for the given unsigned type) is the result.
Many popular C++ compilers and hardware return the same bit pattern for int
as they would for unsigned int
interpreted by 2s complement logic, but that is not required by the standard.
So L'A' + 1
involves converting L'A' to an int
, adding 1
as an int
.
If we add the missing bit:
wchar_t bob = L'A' + 1;
we can see where the warning occurs. The compiler sees someone converting an int
to a wchar_t
and warns them. (this makes more sense when the values in question are not compile time constants)
If we make it explicit:
wchar_t bob = static_cast<wchar_t>(L'A' + 1);
the warning (probably? hopefully?) goes away. So long as the right hand side results in being in the range of valid wchar_t
values, you are golden.
If instead you are doing:
wchar_t bob = static_cast<wchar_t>(L'A' + x);
where x
is an int
, if wchar_t
is signed you could be in trouble (unspecified result if x
is large enough!), and if it unsigned you could still be somewhat surprised.
A nice thing about this static_cast
method is that unlike (wchar_t)x
or wchar_t(x)
casts, it won't work if you accidentally feed pointers into the cast.
Note that casting x
or 1
is relatively pointless, unless it quiets the compiler, as the values are always up-converted (logically) into int
s prior to +
operating (or unsigned int
s if wchar_t
is unsigned and the same size as an int
). With int
significantly larger than wchar_t
this is relatively harmless if wchar_t
is unsigned, as the back-conversion is guaranteed to do the same thing as adding in wchar_t
mod its power of two, and if wchar_t
is signed leaving the gamut gives an unspecified result anyhow.
So, cast the result using static_cast
. If that doesn't work, use a bitmask to explicitly clear bits you won't care about.
Finally, VS2013 uses 2s complement math for int
. So static_cast<wchar_t>(L'A' + x)
and static_cast<wchar_t>( L'A' + static_cast<wchar_t>(x))
always produce the same values, and would do so if wchar_t
was replaced with unsigned short
or signed short
.
This is a poor answer: it needs curation and culling. But I'm tired, and it might be illuminating.