c++11vectorcompiler-errorsstl

In the c++ vector, why cannot we print iterator value individually?


In the following code, I get an error if I type either of the following two

cout << "value of it: " << vec.begin() << endl;

cout << "value of it: " << it << endl;

But if I write following, I do not get error:

cout << "value of it: " << it-Vec.begin() << endl;

Why is that?

#include <iostream>
#include <vector>
#include <algorithm>

using std::cout;
using std::endl;
using std::vector;

int main(){

    vector<int> Vec{1, 20, 3, 14, -5, 6, 1, 8, 0, 7 };    
    std::sort(Vec.begin(), Vec.end());
   
    int find_Y = 3;
    auto it = std::lower_bound(Vec.begin(), Vec.end(), find_Y);

    cout << "value of it: " << it << endl; // This gives error!!
    cout << "Value of *it: " << *it << endl;
    cout << "Index of Y: " << it - Vec.begin() << endl;   

}

Solution

  • You may think of an iterator as a pointer. Unless you define cout operator << on an iterator, you get a compiler error.
    Vec.begin() returns an iterator that points to the first element of Vec.
    auto it = std::lower_bound also returns an iterator. So, it is not surprising that cout << iterator gives an error:
    error: no match for 'operator<<' (operand types are 'std::basic_ostream<char>' and '__gnu_cxx::__normal_iterator<int*, std::vector<int> >')

    You can safely dereference Vec.begin() to see the the value, Vec[0].
    You can safely dereference the lower_bound return iterator provided that the iterator is not Vec.end().

    But if I write following, I do not get error:
    cout << "value of it: " << it - Vec.begin() << endl;

    Just like in C's pointer arithmetic, you can subtract two iterators. See @Jason R's answer here:
    How does subtracting X.begin() return the index of an iterator?

    Suppose it points to Vec.begin(), then the difference is 0. If it points to (Vec.begin() + 1), then the difference is 1.

    If you are unfamiliar with C pointer arithmetic, please read section, "Pointer arithmetics" here: https://cplusplus.com/doc/tutorial/pointers/

    Here is your modified program to illustrate the above points:

    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    using std::cout;
    using std::endl;
    using std::vector;
    
    int main(){
    
        vector<int> Vec{1, 20, 3, 14, -5, 6, 1, 8, 0, 7 };    
        std::sort(Vec.begin(), Vec.end());
    
        for( auto val:Vec) { cout << val << " "; } std::cout << std::endl; // -5 0 1 1 3 6 7 8 14 20
    
        cout << "*Vec.begin() = " << *Vec.begin() << ";  *(Vec.end() - 1) = " << *(Vec.end() - 1) << endl; // -5  20
       
        int find_Y = 3;
        auto it = std::lower_bound(Vec.begin(), Vec.end(), find_Y);
        // Deference it if allowed
        if( it != Vec.end() )
        {
            // cout << "value of it: " << it << endl; // This gives error!!
            cout << "value of *it: " << *it << endl; // This fixes error.
            cout << "Index of Y: " << it - Vec.begin() << endl;
        }
        else
        {
            cout << "find_y exceeds max value in Vec" << endl;
            cout << "Index of Y: " << it - Vec.begin() << endl;
        }
    }
    

    Output:

    -5 0 1 1 3 6 7 8 14 20
    *Vec.begin() = -5;  *(Vec.end() - 1) = 20
    value of *it: 3
    Index of Y: 4
    

    You can change values of find_Y to, say 21, to execute the else condition.