I'm writing a file I/O DLL in C++ which is going to be used from VB6. The interface is already fixed, and uses INT64/Currency as the general integer data type.
Now I have this function:
extern "C" LPWIN32_FIND_DATAW ZFILEIO_API GetFileInfoByIndex(INT64 index) {
return total_size >= 0
&& index <= file_vec->size()
&& index >= 0
? &file_vec->at(index)
: NULL;
}
where file_vec
is of type std::vector<WIN32_FIND_DATAW>
. Its at
member function takes a size_t
argument, which is in my case an unsigned 32-bit integer. Therefore, MSVC++2010 warns me of possible data loss. I think nothing can happen in my code, but please correct me if I'm wrong. Also, do you know a method to avoid the warning (without shutting it off for other places in my code)?
And then there's another question; I would like to return the WIN32_FIND_DATAW
struct by value, not as a pointer, but that's not possible because then I can't return NULL for illegal requests. Can I return such a pointer to my internal data to a VB6 application?
2 Answers 2
Your types are not the same, and you're relying on implicit conversion. The compiler is warning you because not all implicit conversions in this case will be valid. If you know that the conversion is valid in your case, then you should do the conversion explicitly. It's sensible to check the condition you're relying on:
extern "C" LPWIN32_FIND_DATAW ZFILEIO_API GetFileInfoByIndex(INT64 index) {
assert(index <= SIZE_MAX);
return total_size >= 0
&& index <= file_vec->size()
&& index >= 0 ? &file_vec->at(static_cast<size_t>(index)) : NULL;
}
The check can be either an assert or throw an exception, depending on how confident you are that this condition cannot (even theoretically) be hit in your code. You may also want to make sure that the range of index
is checked at a higher level in the code where it can throw a more meaningful exception, e.g. in the constructor of the corresponding type. Even if you do this, keeping an additional check in the code just prior to the cast is useful, because it verifies to a future maintainer that the cast is valid.
If the compiler still complains when you have the explicit cast in place, then I think your only option is to temporarily silence the warning. I still prefer the cast solution even in this case, since it's obvious to the reader that something potentially dangerous is being done.
Note that SIZE_MAX
is not defined in the C++ standard AFAICT. It's likely to be available on your platform, but if not there's almost certainly another way of getting the same information, namely the maximum value of size_t
.
-
1\$\begingroup\$ As an example example of the last sentence
std::numeric_limits<size_t>::max()
. \$\endgroup\$Mark B– Mark B2011年06月21日 20:13:44 +00:00Commented Jun 21, 2011 at 20:13 -
1\$\begingroup\$
SIZE_MAX
is in the C++ standard library since C++11. \$\endgroup\$L. F.– L. F.2019年08月26日 11:46:32 +00:00Commented Aug 26, 2019 at 11:46
#pragma warning(disable:4xxx)
yourcode();
#pragma warning(default:4xxx)
Where 4xxx is the warning code.
Have a look at the msdn article
-
3\$\begingroup\$ Thanks. I usually do it with the warning push and warning pop pragmas ... I wonder whether I can really suppress the cause of the warning, however. \$\endgroup\$Felix Dombek– Felix Dombek2011年05月25日 20:56:41 +00:00Commented May 25, 2011 at 20:56