This code snippet works well on my test project. But it compiles with warnings on my working project
auto current_date = boost::gregorian::day_clock::local_day();
const auto nMinYear = current_date.year(); const auto nMonth = current_date.month(); const auto nDay = current_date.day();
const auto nMinYear1 = nMinYear + 1;
boost::gregorian::date holidayDate1(nMinYear1, nMonth, nDay);
at the line of holidayDate1 construction.
Warning C4244 'argument': conversion from 'unsigned int' to 'unsigned
short', possible loss of data
My test project is on boost-1.72 and working project on 1.75, both are on Visual Studio 2019.
And I tried using grep_year to wrap nMinYear1 -- holidayDate1(grep_year(nMinYear1 )) -- it doesn't compile.
Edit:
I just tried a forced casting can work around it,
boost::gregorian::date holidayDate1((unsigned short)nMinYear, (unsigned short)nMonth, (unsigned short)nDay);
But I don't understand why the warning happens.
The type of
nMinYear + 1
will be an unsigned int due to implicit widening of the terms in that expression. So nMinYear1 is a const unsigned int, and the compiler emits a warning when that's used in the boost::gregorian::date constructor.
decltype(nMinYear) nMinYear1 = nMinYear + 1;
is a fix.
Related
I compiled the following code with -Wsign-conversion :
int main()
{
unsigned int a = 8;
int b = a + 8u; // warning: implicit conversion changes signedness: 'unsigned int' to 'int'
int c = a - 8u; // warning: implicit conversion changes signedness: 'unsigned int' to 'int'
int d = a * 8u; // warning: implicit conversion changes signedness: 'unsigned int' to 'int'
int e = a / 8u; // gcc warns, but no warning in clang
}
Clang doesn't emit a warning when assigning from the result of an unsigned division, but gcc does.
Why is there a difference in this one particular case?
Clang is just being an extra bit clever: division of an unsigned integer by an unsigned integer larger or equal to 2 means the unsigned integer result will always fit in the signed integer counterpart (to that of the numerator type in the division expression). However, if you divide by an unsigned integer valued 1, the result is no longer guaranteed to fit in a signed integer counterpart, and Clang does emit a warning:
#include <cstdint>
int main() {
uint8_t a = 240; // '240 / 1' will not fit in int8_t
int8_t e = a / 2u; // No warning in clang
int8_t f = a / 1u; // warning: implicit conversion changes signedness: 'unsigned int' to 'int8_t' (aka 'signed char') [-Wsign-conversion]
}
One could also argue that Clang should be able to omit the warning for the similar special case of multiplication by 0; however Clang does not whereas GCC, instead, does:
// Clang warns, no warning in GCC.
int8_t g = a * 0u;
So peculiarly Clang is clever, in this context, w.r.t. division and GCC w.r.t. multiplication.
Finally, note that the gating for Clang to emit this warning during division seems to be only when dividing by 1, as you will not get the same -Wsign-conversion if you divide by 0u; arguably as it has been overridden by the more relevant (in such a context) -Wdivision-by-zero warning:
int8_t h = a / 0u;
warning: division by zero is undefined [-Wdivision-by-zero]
I am trying to compile some library code and ran into an error; I simplified the example and I have the following MVCE which fails to compile with MSVC 2019 with the error
error C2440: 'return': cannot convert from 'const char *' to 'const char (&)[20]'
static constexpr const char somethingWeird[] = "Well, that's odd...";
void fail() { throw 0; }
// This doesn't work
constexpr const char(&checkNullTerminatedGood(const char(&a)[20]))[20]{
return a[19] == char(0) ? decltype(a)(a) : (fail(), decltype(a)(a));
}
static constexpr const auto somethingElseNew = checkNullTerminatedGood(somethingWeird);
When I convert the ternary operator to a proper if-statement, the code compiles well:
static constexpr const char somethingWeird[] = "Well, that's odd...";
void fail() { throw 0; }
// This works
constexpr const char(&checkNullTerminatedGood(const char(&a)[20]))[20]{
if (a[19] == char(0)) {
return decltype(a)(a);
} else {
return (fail(), decltype(a)(a));
}
}
static constexpr const auto somethingElseNew = checkNullTerminatedGood(somethingWeird);
Is this a bug in MSVC? The first snippet compiles with GCC and Clang.
A bit of googling shows this is know problem which is claimed to be fixed (but it is not).
C++ Overly aggressive decay of static array to pointer in ternary operator - Developer Community
Solution
by Leo Zhang [MSFT] Sep 07, 2017 at 02:35 AM
Thank you for your feedback! This issue has been fixed and it will be available in the next update to Visual Studio 2017. Thank you for helping us build a better Visual Studio!”
I have an std::array<unsigned, 3> defined inside a class. I want to initalise it inside the constructor, like this:
MyClass::MyClass(std::map<std::string, std::string> const&data)
{
MyArr[0] = (unsigned)(std::atoi(data["one"].c_str()));
MyArr[1] = (unsigned)(std::atoi(data["two"].c_str()));
MyArr[2] = (unsigned)(std::atoi(data["three"].c_str()));
}
By compiling this code in the latest MSVC release with
cl /EHsc /O2 /std:c++17 main.cpp
I get
error C2397: conversion from 'int' to 'unsigned int' requires a narrowing conversion
it points to the line 2 if the snippet.
Use the appropriate function to convert string to an unsigned integer:
char* end;
MyArr[0] = std::strtoul(data["one"].c_str(), &end, 10);
You might also need to define your array as std::array<unsigned long, 3>.
In Visual C++ 2012 the code
double d = 0.5;
float f = d;
int i = f;
issues 2 warnings for me:
test.cpp(26): warning C4244: 'initializing' : conversion from 'double' to 'float', possible loss of data
test.cpp(27): warning C4244: 'initializing' : conversion from 'float' to 'int', possible loss of data
I want to suppress the first warning which I consider spam, but keep the second warning which I consider very helpful. Is it possible to suppress the one and keep the other? Do people generally just suppress them all? We had a bad bug where we mistakenly passed a double to a float. But we tons of our math code would trigger the double->float warnings.
Don't suppress warnings that are designed to prevent potential bugs. Tell the compiler you know what you are doing instead by casting:
double d = 0.5;
float f = static_cast<float>(d);
int i = static_cast<int>(f);
I have such codee:
struct Foo {
unsigned attr : 7;
std::pair<char *, unsigned> f() {
char *ch = nullptr;
return std::make_pair(ch, static_cast<unsigned>(attr));
}
};
MSVS2013 give me something like this error:
can not convert 'unsigned int' to 'unsigned int&'
While gcc 4.8 and clang 3.3 compile such code without errors.
Is this MSVS compiler bug? If so, where I should report it?
Compiles and works just fine in VS2010. Must be a bug. Report it to Microsoft Connect: https://connect.microsoft.com/VisualStudio