We have an emulated unsigned integer type, let's call it uint_t
, which has operator unsigned int()
implemented.
When we use a variable of this type as an array index:
#pragma warning(disable: 4514) // unreferenced inline function removed
#pragma warning(disable: 4710) // function not inlined
#pragma warning(disable: 4711) // function selected for inline expansion
#include <cstdio>
class my_uint_t
{
public:
my_uint_t(unsigned int val) { m_val = val; }
operator unsigned int() const { return m_val; }
unsigned int operator ++(int) { return m_val++; }
private:
unsigned int m_val;
};
int main(int, const char **)
{
const char *myArray[] = { "1", "2", "3", "4", "5" };
for (my_uint_t i = 0; i < sizeof(myArray)/sizeof(myArray[0]); i++)
{
printf("%s\n", myArray[i]);
}
for (unsigned int i = 0; i < sizeof(myArray)/sizeof(myArray[0]); i++)
{
printf("%s\n", myArray[i]);
}
return 0;
}
and compile it in Visual C++ 2015 x86 with all warnings enabled, we get this warning:
warning C4365: 'argument': conversion from 'unsigned int' to 'int', signed/unsigned mismatch
According to the C++ language spec (from http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf)
8.2.1 Subscripting
1 A postfix expression followed by an expression in square brackets is a postfix expression. One of the expressions shall be a glvalue of type “array of T” or a prvalue of type “pointer to T” and the other shall be a prvalue of unscoped enumeration or integral type. The result is of type “T”. The type “T” shall be a completely-defined object type.66 The expression E1[E2] is identical (by definition) to *((E1)+(E2))...
Why does Visual C++ not accept a class with a single cast operator to unsigned int
as an "integral type"?
Note: it is happy with the line using a real unsigned int, but not with the class with the unsigned int operator.
Note also: this only happens in x86 (32-bit) builds, not x64.