Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does the C++ standard say about std::vector<int> v1,v2; std::distance(v1.begin(),v2.begin())?

I have this code

#include <vector> #include <iostream>  int main(int argc, char* argv[]) {    std::vector<int> v1,v2;    std::cout << std::distance(v1.begin(),v2.begin());    return 0; } 

and it has a bug because it is not meaningful to compare the iterators of two different vectors.

I had a look at N3376 at 24.4.4 Iterator operations at page 815:

template<class InputIterator> typename iterator_traits<InputIterator>::difference_type distance(InputIterator first, InputIterator last); 

Requires: If InputIterator meets the requirements of random access iterator, last shall be reachable from first or first shall be reachable from last; otherwise, last shall be reachable from first.

Now I think that Requires is not fulfilled.

What does the standard state should happen in this case?

like image 907
Alessandro Jacopson Avatar asked Apr 15 '15 15:04

Alessandro Jacopson


People also ask

What is std :: distance?

std::distanceCalculates the number of elements between first and last . If it is a random-access iterator, the function uses operator- to calculate this. Otherwise, the function uses the increase operator ( operator++ ) repeatedly.

What is an std :: vector?

1) std::vector is a sequence container that encapsulates dynamic size arrays. 2) std::pmr::vector is an alias template that uses a polymorphic allocator. The elements are stored contiguously, which means that elements can be accessed not only through iterators, but also using offsets to regular pointers to elements.

What is the correct way to initialize vector in C++?

Begin Declare v of vector type. Call push_back() function to insert values into vector v. Print “Vector elements:”. for (int a : v) print all the elements of variable a.

Do I need to initialize a vector in C++?

The vector in C++ stores the reference of the objects and not the data directly. These objects can be of any data type like integer, char, string, etc. Unlike static containers like an array, a vector does not need a size to be initialized with.


2 Answers

[iterator.requirements.general]:

An iterator j is called reachable from an iterator i if and only if there is a finite sequence of applications of the expression ++i that makes i == j.

The problem is that once you incremented v1.begin() v1.size()-1 times, the next increment operation induces undefined behavior, so v2.begin() cannot be reached from v1.begin(). The same argument makes v1.begin() unreachable from v2.begin().


In case your question was "What happens if a condition in a Requires section is violated?", look at [res.on.required]:

Violation of the preconditions specified in a function’s Requires: paragraph results in undefined behavior unless the function’s Throws: paragraph specifies throwing an exception when the precondition is violated.

like image 188
Columbo Avatar answered Oct 26 '22 22:10

Columbo


In some implementations of std::distance, the first iterator is incremented until it reaches the second iterator. The iterations are counted:

unsigned int counts = 0; while (iter1 != iter2) {   ++counts;   ++iter1; } 

If the iterators point to containers in different address spaces, the loop many not terminate. Using the terms in the standard, the second iterator is not reachable.

like image 21
Thomas Matthews Avatar answered Oct 26 '22 23:10

Thomas Matthews