What is the best strategy to get rid of "warning C4267 possible data loss"?

I ported some legacy code from win32 to win64. Not because the size of the win32 object was too small for our needs, but only because win64 is now more standard, and we want to transfer all our environments to this format (and we also use some third-party libraries that offer better performance in 64 bits, than 32 bits).

As a result, we get tons;

warning C4267: 'argument': conversion from 'size_t' to '...', possible data loss

Mostly because of code like: unsigned int size = v.size(); where v is the STL container.

I know why the warning makes sense; I know why it is issued and how it can be fixed. However, in this particular example, we never faced situations when the size of the container exceeded the unsigned int max value in the past .... therefore, there will be no reason for this problem when porting code to a 64-bit environment.

We had discussions about what would be the best strategy to suppress these noise alerts (they might hide the corresponding one that we will skip), but we could not decide on the appropriate strategy.

So, I ask the question here, what would be the best recommended strategy?

1. Use static_cast

Use static_cast . Make unsigned int size = static_cast<unsigned int>(v.size()); . I don’t β€œlove” because we lose the ability to 64 bits to store a huge amount of data in the container. But since our code never reached the limit of 32 bits, so this seems like a safe solution ...

2. Replace unsigned int with size_t

This is definitely more complex than the unsigned int size object in the above example can be ported to other functions stored as a class attribute, and then deleting a single-line warning can result in hundreds of code changes ...

3. Disable warning

This is most likely a very bad idea, as it will also disable the warning in this case uint8_t size = v.size() , which, of course, can lead to data loss ....

4. Define the "safe casting" function * and use it

Something like :

 template <typename From, typename To> To safe_cast( const From& value ) { //assert( value < std::numeric_limits<To>::max() && value > std::numeric_limits<To>::min() ); // Edit 19/05: test above fails in some unsigned to signed cast (int64_t to uint32_t), test below is better: assert(value == static_cast<From>(static_cast<To>(value))); // verify we don't loose information! // or throw.... return static_cast<To>( value ); } 

5. Other solutions are welcome ...

"Use solution 1 in this case, but 2 in this case" perfectly might be a good answer.

+7
c ++ casting windows porting suppress-warnings
source share
2 answers

Use the correct type (option 2) - the function / interface defines this type for you, use it.

 std::size_t size = v.size(); // given vector<>::size_type is size_t // or a more verbose decltype(v)::size_type size = v.size(); 

This goes to the intention ... you get size from v and that size is of type. If the correct type was used from the very beginning, that would not be a problem.

If you need this value later as a different type, then convert it; safe_cast<> is a good alternative that includes checking runtime bounds.

Option 6. Use auto

When you use size = v.size() , if you are not worried about the type of this type, only if you use the correct type,

 auto size = v.size(); 

And let the compiler do the hard work for you.

+8
source share

IFF you have temporary pressure to get a warning code for free, I would first turn off the warning - your code used to work with this, and this, IMHO, it is extremely unlikely that in cases where you assign a 32-bit size, which you will exceed. (4 G in the collection - I doubt that you will fly in regular applications.)

Moreover, for cases other than collections, the warning certainly has its merits, so try to include it sooner or later.

Secondly, when turning on and fixing the code, my priority would be as follows:

  • Use auto (or size_t pre C ++ 11) for local area networks where this value no longer narrows.
  • If you need to narrow it down, use safe_cast if you can justify the overhead associated with introducing it to your team. (training, coercion, etc.).
  • Otherwise, just use static_cast :

    I do not think this is a problem with collections. Unless you know better about the opposite, there will never be more than 4G items in your collection. IMHO, it is simply pointless to have so much data in the collection for any ordinary use cases in the real world. (not to say that it may not be an accidental case when you need such large data sets, you just know when it will be so.)

    In cases where you are not actually narrowing the collection counter, but some other numeric ones, narrowing is probably problematic, so there you will correct the code accordingly.

-one
source share

All Articles