I've been trying to get rid of warnings in some older code (must use MSVC 2005, currently working with a 32 bit build), but have been struggling to get rid of a size_t
to unsigned int
conversion warning. We have our own Array<T>
implementation of a growing array that implements an
template<typename I> const T& at(const I i) const {return atImpl(i);}
method. When called as
size_t i = 10; myArray.at(i);
I get a conversion from 'size_t' to 'const unsigned int', possible loss of data
warning. A working theory has been that I
is understood to be unsigned int
, which is causing compiler to cast/convert the size_t
to unsigned int
when passing i
to at
(which would have been inconvenient but acceptable). However, I haven't been able to reproduce this warning in neither a minimal working example (bottom of this post), nor in more complex minimal examples. Simply casting the parameter to unsigned int
makes the warning disappear and would be enough for our needs (by contract, the number fits within an unsigned int
)
I
being unsigned int
in such a call correct (spec says "A typedef-name is thus a synonym for another type. A typedef-name does
not introduce a new type", typeid(size_t(1)).name()
says unsigned int
and size_t
seems to be typedef
fed). In other words, should or should not the minimal example give the warning? The build configuration is the same, as far as I can tell.Thanks
The minimal example:
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;
}
The at function is also templated. C++ will try to deduce the template type argument. Which is what is happening in your code since you are not specifying the type in the call such as a.at< size_t>(1);
This code will generate a warning because it has deduced the type as a unsigned int and then we try to pass an 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;
}
EDIT: I actually tried this code in VS and it generates the warning.
Edit2: In the code I tried size_t and unsigned int are both also 4 bytes. So I did some digging. In older versions of VS size_t is defined as typedef __w64 unsigned int size_t
The '__w64' is now deprecated but was used to flag types that would have a different size (eg 64 vs 32) when moving to a 64 bit platform. The __w64 causes the compiler to see size_t
as a different type.
As an experiment I typedefed my own unsigned int myint
and changed the line size_t i = 10
to myint i = 10
.
using typedef __w64 unsigned int myint
generates the warning where as 'typedef unsigned int myint` does not generate a warning.