What type should be used for iterator difference to avoid warnings of "possible data loss"?

I need a general rule for warnings in x64 mode. Which way is better?

Consider the following lines of some code

const int N = std::max_element(cont.begin(), cont.end()) - cont.begin(); 

or

 const int ARR_SIZE = 1024; char arr[ARR_SIZE]; //... const int N = std::max_element(arr, arr + ARR_SIZE) - arr; 

This is my regular code. I have no problem with x86.

But if I run the compiler in x64 mode, I have some warnings:

 conversion from 'std::_Array_iterator<_Ty,_Size>::difference_type' to 'int', possible loss of data conversion from '__int64' to 'int', possible loss of data 

I want to solve these problems as a general rule. Which way is better?

  • Creating static_cast :

     const int N = static_cast<int>( std::max_element(cont.begin(), cont.end()) - cont.begin() ); 

    I think this is not universal. And too many letters.

  • Replace the output type with ptrdiff_t :

     const ptrdiff_t N = std::max_element(cont.begin(), cont.end()) - cont.begin(); 

    What should I do with this unknown type of ptrdiff_t? Then I will get a few dozen warnings. I want to do a lot of operations with N: saving, adding, multiplying, loops, etc. Important: but what if std::_Array_iterator<_Ty,_Size>::difference_type and ptrdiff_t are different types?

  • Change the output type to std::_Array_iterator<_Ty,_Size>::difference_type :

     //h-file struct S { type mymember; // What is the type? }; //cpp-file typedef std::vector<int> cont_t; const cont_t::difference_type N = std::max_element(cont.begin(), cont.end()) - cont.begin(); // Save N S mystruct; mystruct.mymember = N; // What type of mystruct.mymember? 

    How do I save N? What type of mystruct.mymember? I do not know this in the h file.

  • Your choice.

+4
source share
6 answers

"what if std::_Array_iterator<_Ty,_Size>::difference_type and ptrdiff_t are different types?" Do not use such a compiler. In addition, it is likely that it cannot formally differ. For instance. this is the case for vector using the standard default allocator, since the one where it retrieves its typedefs, but since the formal guarantee does not matter (he is, it really is not) I will not look at this in C ++ 0x draft .

So use ptrdiff_t .

But it might be a good idea to add a few typedef, for example

 typedef ptrdiff_t Size; typedef ptrdiff_t Index; 

and then in your specific case you use Index .

These typedefs, of course, are accompanied by customizable stand-alone functions countOf , startOf and endOf , which allow handling raw arrays and containers of the standard library in exactly the same way.

If you see the name Index , then it’s more clear that this is an index that, naturally, cannot get out of the set of Index or Size types almost regardless of what you do. For example, add something else to it, Index . So basically there won't be β€œanother dozen warnings.”

But in some rare cases, you need to switch from Index to just int , say. In and on these rare occasions, just do static_cast to shut down the compiler and make your intention clear. Or even the usual static_cast -like narrowTo operation, for expressiveness ...

Cheers and hth.,

+3
source

To save the result of max_element () - cont.begin (), you should use

 struct Foo { std::vector<int>::difference_type n; }; 

or

 template<typename T> struct Foo { std::vector<T>::difference_type n; }; 

or

 template<T> struct Foo { T n; }; 

Because the differ_type parameter uses the difference_value, and when you send it to int, you get undefined behavior.

You can use & * c.begin () to convert an iterator to a pointer and use ptrdiff_t to distinguish these pointers.

+1
source

I would use std::ptrdiff_t .

I cannot come up with a reasonable implementation where std::vector<T>::iterator::difference_type will not be assigned to std::ptrdiff_t . They will almost certainly be the same. If they do not match, the difference_type must be less than ptrdiff_t .

In addition, ptrdiff_t is a signed type, so if all of your code is designed to work with int s, you would be better off than trying to use an unsigned type, such as std::vector<int>::size_type .

+1
source

In visual-studio-2010 you can write:

 const auto N = std::max_element( cont.begin(), cont.end() ) - cont.begin(); 
0
source

My solution is to use a type that is known to be large enough based on domain knowledge that I have, but which may not be available to the compiler. If the compiler then complains about a possible data loss, I add a cast (which is guaranteed to be safe, because I know in advance that the target type should be large enough).

0
source

Use std::vector<int>::size_type :

  • Representation of any non-negative value difference_type guaranteed
  • This is what accepts all vector indexing operations.
  • If cont is cont empty, std::max_element(cont.begin(), cont.end()) - cont.begin(); will not evaluate a negative value. If it is empty, you still should not do any processing.

What should I do with this "unknown" type? Then I will get a few dozen warnings. I want to do a lot of operations with N: saving, adding, multiplying, loops, etc.

You will not receive any warnings if you use the type consistently and restrict its use where you really need it. N is the index into the vector; that all this is good. Any significant operation that you perform on it will result in another possible index into the vector.

0
source

All Articles