4

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?

Bista
  • 7,869
  • 3
  • 27
  • 55
Harikrishna R
  • 317
  • 1
  • 4
  • 11
  • Possible duplicate of [warning C4244: 'argument' : conversion from 'time\_t' to 'unsigned int', possible loss of data -- C++](http://stackoverflow.com/questions/9246536/warning-c4244-argument-conversion-from-time-t-to-unsigned-int-possible) – roottraveller Jan 06 '16 at 12:22
  • 2
    @rkm_Hodor_king Not really. – πάντα ῥεῖ Jan 06 '16 at 12:33

3 Answers3

1

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 of std::size_t, similar to the POSIX type ssize_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++.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • What about `unsigned int u = (int)-1;`? What would you expect `u` to be? Would you consider this data loss? Should the compiler issue a warning? – Yuval Mar 30 '20 at 14:27
1

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.

paulm
  • 5,629
  • 7
  • 47
  • 70
0

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;
}

Yuval
  • 3,207
  • 32
  • 45