c++ 我怎样才能得到一个指向最后一个元素的前向迭代器?

ljo96ir5  于 2023-05-02  发布在  其他
关注(0)|答案(2)|浏览(114)

我正在寻找一个方便的选项来从只支持前向遍历的容器/范围中获取最后一个元素,这意味着我不能做std::prev(std::end())之类的事情。现在我唯一的想法是:

const std::forward_list<int> list{1, 2, 3, 4, 5};
auto it = list.cbegin();
std::advance(it, std::distance(it, list.cend()) - 1);
std::cout << *it << std::endl;

有没有更方便的方法到达前向遍历范围的最后一个元素?Boost是受欢迎的。

u59ebvdq

u59ebvdq1#

创建一个辅助函数,迭代直到下一个函数结束

template<class iterator>
iterator find_next_to_last(iterator first, iterator last) {
    assert(first != last);
    iterator next = first;
    while(++next != last)
        first = next;
    return first;
}
jv4diomz

jv4diomz2#

我喜欢Mooing Duck的答案,但我认为一个处理空列表的小调整会很好。虽然通过契约禁止这种情况没有什么错,但标准库中的许多函数都通过契约施加了约束。
但要回答你的问题。..
有没有更方便的方法到达前向遍历范围的最后一个元素?
......不......一般没有更方便的方法。您需要遍历前向列表以到达最后的元素。(假设你不能缓存迭代器到最后一个元素。)

#include <forward_list>
#include <iostream>
#include <iterator>
#include <utility>
#include<cassert>

template <typename I>
auto back(I it, I last) {
    using std::next;
    auto n = it;

    while (n != last) {
        it = std::exchange(n, next(n));
    }

    return it;
}

// Container-to-iterator-pair convenience function.
template <typename C>
auto back(C const& c) {
    using std::begin;
    using std::end;
    return back(begin(c), end(c));
}

static
auto operator<<(std::ostream& out, std::forward_list<int> const& l) -> std::ostream& {
    auto sep = "";

    for (auto&& x : l) {
        out << std::exchange(sep, " ") << x;
    }

    return out;
}

template <typename C, typename I>
struct print {
    C const& container;
    I const& it;
    print(C const& c, I const& i) : container{c}, it{i} {}
    bool valid() const {
        using std::begin;
        using std::end;
        using std::next;
        auto b = begin(container);
        auto e = end(container);
        while(b != e) {
            if (it == b) return true;
            b = next(b);
        }
        return it == e;
    }

    template <typename CC, typename II>
    friend auto operator<<(std::ostream& out, print<CC, II> const& p) -> std::ostream& {
        using std::end;
        assert(p.valid());

        if (end(p.container) == p.it) {
            return out << "(end)";
        }

        return out << *p.it;
    }
};
print(struct allow_ctad_t, struct allow2_ctad_t)->print<void, void>;

int main() {
    std::forward_list<int> const list{1, 2, 3, 4, 5};
    std::cout << list << "\n";
    auto it = back(list);
    std::cout << print(list, it) << "\n";
    std::cout << print(list, list.end()) << "\n";
}

相关问题