On Visual C++ 2019:
The following code renders the warning:
warning C4267: 'argument': conversion from 'size_t' to 'DWORD', possible loss of data
HANDLE events[2];
WaitForMultipleObjects(std::size(events), events, FALSE, INFINITE);
But using _countof(events)
won't give any warning. Note that std::size
's template overload function is called.
This one:
template<class _Ty,
size_t _Size> inline
constexpr size_t size(const _Ty(&)[_Size]) _NOEXCEPT
{ // get dimension for array
return (_Size);
}
Which essentially is returning a size_t
, and the function is constexpr
. And that's why array declaration works:
HANDLE Events[2];
int arr[std::size(Events)];
But following code won't compile without warning:
DWORD sz1 = std::size(Events);
This is okay:
DWORD sz2= _countof(Events);
Any specific reason, or a compiler bug?
Relevant: What is the return type of sizeof operator?
EDIT, Interestingly, these would also work fine:
HANDLE events[2];
constexpr size_t s1 = sizeof(Events) / sizeof(Events[0]);
constexpr size_t s2 = std::size(Events);
The variables s1
and s2
are taken as true compile-time values, but not std::size()
's result itself!
DWORD
is always 32-bit unsigned on Windows.size_t
is typically a 64-bit unsigned long long with a 64-bit compiler. Switch your build to 32-bit and it's a 32-bit unsigned int.Assigning a 64-bit int to a 32-bit - yep, that's a warning condition.
What's weird is this:
Compiles without issue. I'm guessing it's because the compiler can infer the type of that const expression reduces to unsigned int or smaller.
But this:
Generates a nearly identical warning since
count
evaluates to a 64-bit unsigned long long.But this will also compile without warning: