[英]C++ C4244 =': conversion from 'std::streamsize' to 'unsigned short', possible loss of data; any solution?
[英]C4244: '+=' : conversion from 'std::streamsize' to 'size_t', possible loss of data
我已经将我的 VC++ 项目从 VS2008 迁移到 VS2013 并收到一些警告,例如:
C4244: '+=': conversion from 'std::streamsize' to 'size_t', possible loss of data.
我该如何解决这些类型的警告?
在 MSVC 2013 std::streamsize
中是:
typedef _Longlong streamsize;
typedef _LONGLONG _Longlong;
#define _LONGLONG __int64
而size_t
是:
typedef unsigned __int64 size_t;
因此,一个简单的重现案例是:
unsigned __int64 b = 1;
__int64 a = b;
但是,这不会发出警告——所以您可能在某处将size_t
重新定义为 32 位?
为清楚起见:
std::streamsize b = 1;
size_t a = 0;
b = a;
也不发出警告。
正如c++ 参考中所述, std::streamsize
被定义为带signed
的(强调我的):
类型
std::streamsize
是有符号整数类型,用于表示 I/O 操作中传输的字符数或 I/O 缓冲区的大小。 它用作std::size_t
的签名副本,类似于 POSIX 类型ssize_t
。
无论如何,似乎没有指定确切的实现。
通常,从有signed
类型到具有相同基数(例如long
)的unsigned
类型的转换不应发出有关可能的数据丢失的警告(除非使用符号指示符)。
这可能是 Visual Studio C++ 中的一个糟糕实现。
这取决于用途。 根据cppreference.com ,
除了在 std::strstreambuf 的构造函数中,从不使用 std::streamsize 的负值。
所以你可以安全地转换你的签名值。
std::streamsize i;
// ...
size_t u = static_cast<size_t>(i);
然而,在更一般的情况下(与 πìντα ῥεῖ 所写的相反),我认为警告是有效的(即使gcc
没有吐出类似的警告)。 比较有符号和无符号值时,最好明确说明您的意思。
您可以强制使用无符号性,例如使用如下代码片段(感谢一般形式的这个问题):
#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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.