I have migrated my VC++ project form VS2008 to VS2013 and got some warnings like:
C4244: '+=' : conversion from 'std::streamsize' to 'size_t', possible loss of data.
How can I resolve these type of warnings?
I have migrated my VC++ project form VS2008 to VS2013 and got some warnings like:
C4244: '+=' : conversion from 'std::streamsize' to 'size_t', possible loss of data.
How can I resolve these type of warnings?
As it's stated in the c++ reference, std::streamsize
is defined as signed
(emphasis mine):
The type
std::streamsize
is a signed integral type used to represent the number of characters transferred in an I/O operation or the size of an I/O buffer. It is used as a signed counterpart ofstd::size_t
, similar to the POSIX typessize_t
.
Anyways, the exact implementation seems not to be specified.
Usually a conversion from signed
to unsigned
type with the same base (e.g. long
) shouldn't issue a warning about possible data loss (unless using the sign indicator is meant).
It's probably a poor implementation in Visual Studio C++.
In MSVC 2013 std::streamsize
is:
typedef _Longlong streamsize;
typedef _LONGLONG _Longlong;
#define _LONGLONG __int64
And size_t
is:
typedef unsigned __int64 size_t;
Thus an easy repro case is:
unsigned __int64 b = 1;
__int64 a = b;
However this doesn't issue a warning - so probably you redefined size_t
somewhere to be 32bits?
For clarity:
std::streamsize b = 1;
size_t a = 0;
b = a;
Also issues no warning.
It depends on the use. According to cppreference.com,
Except in the constructors of std::strstreambuf, negative values of std::streamsize are never used.
So you can safely cast your signed value.
std::streamsize i;
// ...
size_t u = static_cast<size_t>(i);
However, in the more general case (as opposed to what πάντα ῥεῖ wrote), I think the warning is valid (even though gcc
doesn't spit a similar one out). When comparing signed and unsigned values, it's best to be explicit what you mean.
You can force unsigned-ness, e.g. using a code snippet such as the following (thanks to this question for the general form):
#include <iostream>
template <typename T>
typename std::enable_if< std::is_signed<T>::value, typename std::make_unsigned<T>::type >::type
force_unsigned(T u) {
if (u < 0) {
throw std::overflow_error("Cannot use negative value as unsigned type");
}
return static_cast< typename std::make_unsigned<T>::type >(u);
}
template <typename T>
typename std::enable_if< !std::is_signed<T>::value, T >::type
force_unsigned(T u) {
return u;
}
int main() {
std::cout << force_unsigned((unsigned int)1) << std::endl;
std::cout << force_unsigned((int)1) << std::endl;
std::cout << force_unsigned((int)0) << std::endl;
std::cout << force_unsigned((int)-1) << std::endl;
return 0;
}