Search code examples
c++iteratorstdvectorlist-initialization

c++ vector = {vec1.begin, vec1.begin} returns empty vector


I'm trying to understand the behavior of creating a subvector of another vector.

For example, this code: https://godbolt.org/z/PYG34vnTr has a 2-element vector vec1. I want to create a vector of the first element. To get it to work, I had to use:

std::vector<int> vec2 = {vec1.begin(), vec1.begin() + 1};

I'm trying to understand why this is needed. Reason being, I'm doing a recursive loop that halves a vector in each iteration. And the formula:

std::vector<int> vec2 = {vec1.begin(), vec1.begin() + (vec1.size()-1)/2};

Works for all iterations except the one where vec1 is a 2-element vector.

What alternative code should I use?


Solution

  • The end iterator needs to be 1 element beyond the last element you want, which means that the -1 must be removed.

    Illustration:

    #include <iostream>
    #include <vector>
    
    void foo(std::vector<int> inp) {
        for (auto v : inp) std::cout << ' ' << v;
        std::cout << '\n';
    
        if (inp.size() > 1) {
            // the midpoint:
            auto mid = inp.begin() + inp.size() / 2;
    
            std::cout << "L:";
            foo({inp.begin(), mid});
    
            std::cout << "R:";
            foo({mid, inp.end()});
        }
    }
    
    int main() {
        std::vector<int> vec1{1, 2, 3, 4};
        std::cout << "X:";
        foo(vec1);
        std::cout << "Done\n";
    }
    

    Output:

    X: 1 2 3 4
    L: 1 2
    L: 1
    R: 2
    R: 3 4
    L: 3
    R: 4
    Done
    

    Demo


    A non-copying version, working solely with iterators could look like this and gives the same result:

    template<class It>
    void foo(It first, It last) {
        for(auto curr = first; curr != last; ++curr) std::cout << ' ' << *curr;
        std::cout << '\n';
        auto size = std::distance(first, last);
    
        if (size > 1) {
            auto mid = first + size / 2;
            std::cout << "L:";
            foo(first, mid);
            std::cout << "R:";
            foo(mid, last);
        }
    }
    

    Demo