遍历具有自定义开始/结束位置的容器

时间:2020-11-04 11:05:18

标签: c++ iterator containers c++14

我想遍历一个容器(例如std::vector),但不要从头开始。我基本上是在尝试复制boost::make_iterator_range(v.begin() + 1, v.end())

我想到了这个

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

int main()
{
    std::vector<int> v {1, 2, 3};
    
    std::for_each_n(v.begin() + 1, v.size() - 1, [](auto& n) 
    {
        std::cout << n << '\n';
    });
}

但是,这似乎是一个糟糕的解决方案。当我在寻找适用于C ++ 14的解决方案时,它也需要C ++ 17。
在没有第三方库的情况下,有没有更好的方法来实现这一目标?

3 个答案:

答案 0 :(得分:2)

std::for_each在C ++ 11中,您可以这样做:

std::for_each(v.begin() + 1, v.end(), [](auto &n) { ... });

答案 1 :(得分:2)

要复制make_iterator_range,您需要一个具有beginend函数的对象。像这样的东西。

template <typename T>
struct iterator_range {
    iterator_range(T begin, T end) : m_begin(begin), m_end(end) {}

    T begin() {
        return m_begin;
    }

    T end() {
        return m_end;
    }

    T m_begin, m_end;
};

然后,我们可以使我们的make_iterator_range函数返回一个iterator_range

#include <vector>
#include <iostream>

template <typename T>
struct iterator_range {
    iterator_range(T begin, T end) : m_begin(begin), m_end(end) {}

    T begin() {
        return m_begin;
    }

    T end() {
        return m_end;
    }

    T m_begin, m_end;
};

template <typename T>
auto make_iterator_range(T begin, T end) {
    return iterator_range<T>(begin, end);
}

int main()
{
    std::vector<int> v {1, 2, 3};

    auto range = iterator_range<decltype(v.begin())>(v.begin() + 1, v.end());
    
    for (auto& i : range) {
        std::cout << i << '\n';
    }

    for (auto& i : make_iterator_range(v.begin() + 1, v.end())) {
        std::cout << i << '\n';
    }
}

答案 2 :(得分:2)

有没有更好的方法来实现这一目标...

使用范围的解决方案(由cigien提供):

for (int element : v | ranges::drop_view(1))

使用span

的解决方案
for (int element : span(&v[1], v.size() - 1))

当然,直到C ++ 20都没有std::rangesstd::span,因此除非您想使用第三方实现,否则需要编写自己的实现。


如果您不想实现自己的库,也不能使用C ++ 20,也不想使用第三方库,请std::for_each在C ++ 11中。 >