我一直试图摆脱一些旧代码中的警告(必须使用MSVC 2005,目前正在使用32位版本),但一直在努力摆脱size_t
到unsigned int
转化警告。我们有一个实现
Array<T>
实现
template<typename I> const T& at(const I i) const {return atImpl(i);}
方法。当被称为
时 size_t i = 10; myArray.at(i);
我收到conversion from 'size_t' to 'const unsigned int', possible loss of data
警告。 工作理论已经 I
被理解为unsigned int
,这导致编译器在传递时将size_t
转换/转换为unsigned int
i
到at
(本来不方便但可以接受)。但是,我既没有在最小的工作示例(本文的底部),也没有在更复杂的最小示例中重现此警告。简单地将参数转换为unsigned int
会使警告消失,并且足以满足我们的需求(通过合同,数字适合unsigned int
)
I
在这样的调用中unsigned int
的理解是正确的(规范说“因此,typedef-name是另一种类型的同义词.typedef-name确实如此
不引入新类型“,typeid(size_t(1)).name()
说unsigned int
和size_t
似乎是typedef
已经过了。换句话说,应该或不应该是最小的例子发出警告?据我所知,构建配置是一样的。由于
最小的例子:
template<typename T>
class A
{
int t;
public:
template<typename I> T& at(const I i) { return t;}
};
int main()
{
size_t i = 10;
A<int> a;
a.at(i) = 5; // no warning, why?
return 0;
}
答案 0 :(得分:1)
at函数也是模板化的。 C ++将尝试推导出模板类型参数。这是您的代码中发生的事情,因为您没有在调用中指定类型,例如a.at&lt;为size_t&GT;(1);
此代码将生成警告,因为它已将类型推断为unsigned int,然后我们尝试传递size_t
template <typename T>
class A
{
int t;
public:
template<typename I> T& at(const I i)
{ return t;}
};
int main()
{
unsigned int j = 5;
size_t i = 10;
A<int> a;
a.at(j) = 4; // deduce template type as unsigned int
a.at(i) = 5; // generate warning
return 0;
}
编辑:我实际上在VS中尝试了此代码并生成警告。
Edit2:在我尝试过的代码中,size_t和unsigned int都是4个字节。所以我做了一些挖掘。在旧版本的VS中,size_t被定义为typedef __w64 unsigned int size_t
'__ w64'现在已被弃用,但用于标记在移动到64位平台时具有不同大小(例如64对32)的类型。 __w64使编译器将size_t
视为不同的类型。
作为实验,我输入了我自己的无符号整数myint
,并将行size_t i = 10
更改为myint i = 10
。
使用typedef __w64 unsigned int myint
生成警告,其中'typedef unsigned int myint`不会生成警告。