unpredictable level 4 warnings on implicit narrowing conversions in STL
C++ allows many implicit narrowing conversions. These are a serious
weakness in the C++ type system. That's why its important that they are
detected by the compiler. I am using VC++ 2003.
char c = 1.2; // wierd but legal - warning C4244
char d = _T('x'); // ok
char e = L'x'; // ok even if _UNICODE is defined
char f = wchar_t('x'); // ok
char g = wchar_t('256); // warning C4309 "truncation"
2 bytes are converted into 1 byte. I generally set my compiler to
level 4 to make sure I catch these kinds of horrors. Only the first and
last lines above generate warnings. Apparently the compiler judges
that if the higher byte, in a compile time constant expression, is
zero, then a warning is not needed. Im not so sure about whether that
is always appropriate - eg for the very complex expressions that occur
in meta-template programming.
If you try to construct a std::string directly from a wide string, you
will get an error:
wchar_t* p = L"text";
std::string str (p); //error C2664 "cant convert wchar_t to char"
But there are many other ways to mistakenly construct or copy a wide
string into a narrow string. For example std::string has another
constructor that takes InputIterators to start and end of a container.
You can use it like this
wchar_t* p = L"text";
std::string str3 (p, p+4); // !ok but dodgy
You can easily construct a dodgy string from an array of integers:
int a [] = {-1,-2,-3};
std::string str4 (a, a+3); // !ok but dodgy
If I try the same trick with a vector, I get a warning:
wchar_t* p = L"text";
std::vector<char> vc (p, p+6); //warning C4244
But with algorithms it depends. This copiles all too cleanly:
std::vector<int> vi (4, 999); //4 elems of value 999
std::string str5 (4);
std::copy (vi.begin(), vi.end(), str5.begin()); //! ok but dodgy
However if I change vector<int> to vector<long> or vector<short> or
vector<double>, then I do get the expected warning from the copy
algorithm.
I think implicit narrowing conversions are dangerous. As a developer I
want to be careful about them. So I set Level 4 warnings.
At level 4 you expect the compiler to err on the safe side. You
probably dont mind if you get the occasional warning on a line of code
that you feel is safe.
For example you might not mind if you got a level 4 warning on a line
like this:
char c = L'x'; //no warning
If you want avoid the warning, then the compiler should oblige you to
write a cast that alerts the reader that something odd is going on.
char c = static_cast<char>(L'x');
But at level 4, you really do mind if you _dont_ get a warning on lines
like those above labelled "! ok but dodgy"
These warnings seem to be rather unpredictable. So my question is: Am I
missing something? Is it soreally difficult for the compiler to detect
all these conversions? Is this a series of bugs ? Has the behaviour
been changed in VC++ 2005 ?