6
\$\begingroup\$

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?

\$\endgroup\$
10
\$\begingroup\$

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.

\$\endgroup\$
  • 1
    \$\begingroup\$ As an example example of the last sentence std::numeric_limits<size_t>::max(). \$\endgroup\$ – Mark B Jun 21 '11 at 20:13
  • 1
    \$\begingroup\$ SIZE_MAX is in the C++ standard library since C++11. \$\endgroup\$ – L. F. Aug 26 at 11:46
4
\$\begingroup\$
#pragma warning(disable:4xxx)
yourcode();
#pragma warning(default:4xxx)

Where 4xxx is the warning code.

Have a look at the msdn article

\$\endgroup\$
  • 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 May 25 '11 at 20:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.