You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无需创建拼接向量,如何遍历多个同类型std::vector的拼接序列?

遍历多个容器的串行拼接序列(无需创建新容器)

C++标准库本身没有直接提供这种工具,但可以自行实现轻量级适配器,或借助第三方库的现成组件来实现需求。

1. 自行实现zup工具

基于C++20范围特性,可以快速编写一个支持多容器串行遍历的适配器,完全复用原容器的迭代器,不会创建新容器:

#include <vector>
#include <iostream>
#include <ranges>
#include <tuple>

namespace fancy_util {
template<std::ranges::input_range... Ranges>
requires (std::same_as<std::ranges::range_value_t<Ranges>, std::ranges::range_value_t<decltype((Ranges{}, ...))>> && ...)
struct concatenated_range {
    std::tuple<Ranges...> ranges;

    struct iterator {
        using value_type = std::ranges::range_value_t<std::tuple_element_t<0, decltype(ranges)>>;
        using reference = const value_type&;
        using pointer = const value_type*;
        using difference_type = std::ptrdiff_t;
        using iterator_category = std::input_iterator_tag;

        size_t current_range_idx;
        std::tuple<std::ranges::iterator_t<Ranges>...> its;
        std::tuple<std::ranges::sentinel_t<Ranges>...> ends;

        iterator(size_t idx, decltype(its) its_, decltype(ends) ends_)
            : current_range_idx(idx), its(std::move(its_)), ends(std::move(ends_)) {}

        reference operator*() const {
            return *std::get<current_range_idx>(its);
        }

        pointer operator->() const {
            return std::addressof(**this);
        }

        iterator& operator++() {
            ++std::get<current_range_idx>(its);
            if (std::get<current_range_idx>(its) == std::get<current_range_idx>(ends)) {
                if constexpr (sizeof...(Ranges) > current_range_idx + 1) {
                    current_range_idx++;
                }
            }
            return *this;
        }

        iterator operator++(int) {
            auto tmp = *this;
            ++*this;
            return tmp;
        }

        friend bool operator==(const iterator& lhs, const iterator& rhs) {
            if (lhs.current_range_idx != rhs.current_range_idx) {
                return false;
            }
            return std::get<lhs.current_range_idx>(lhs.its) == std::get<lhs.current_range_idx>(rhs.its);
        }

        friend bool operator!=(const iterator& lhs, const iterator& rhs) {
            return !(lhs == rhs);
        }
    };

    iterator begin() {
        return iterator{0, 
            std::apply([](auto&&... r) { return std::make_tuple(std::ranges::begin(r)...); }, ranges),
            std::apply([](auto&&... r) { return std::make_tuple(std::ranges::end(r)...); }, ranges)
        };
    }

    iterator end() {
        return iterator{sizeof...(Ranges)-1, 
            std::apply([](auto&&... r) { return std::make_tuple(std::ranges::end(r)...); }, ranges),
            std::apply([](auto&&... r) { return std::make_tuple(std::ranges::end(r)...); }, ranges)
        };
    }
};

template<std::ranges::input_range... Ranges>
auto zup(Ranges&&... ranges) {
    return concatenated_range<std::decay_t<Ranges>...>{std::make_tuple(std::forward<Ranges>(ranges)...)};
}
} // namespace fancy_util

int main() {
    std::vector<int> vec1{0,1,2};
    std::vector<int> vec2{3,4,5};

    for (const auto& e : fancy_util::zup(vec1, vec2)){
        std::cout << e << ", ";
    }
    // 输出: 0, 1, 2, 3, 4, 5,
    return 0;
}

这个实现支持任意多个同类型输入范围,遍历过程无额外内存开销。

2. 使用第三方库

如果不想自行实现,Boost.Range中的boost::range::join可以直接实现需求,它将多个范围拼接为一个可遍历的视图,无需复制元素:

#include <vector>
#include <iostream>
#include <boost/range/join.hpp>

int main() {
    std::vector<int> vec1{0,1,2};
    std::vector<int> vec2{3,4,5};

    for (const auto& e : boost::join(vec1, vec2)){
        std::cout << e << ", ";
    }
    return 0;
}

Boost.Range的组件经过充分测试,兼容性强,支持多种容器类型。

3. C++23的替代方案(若可用)

C++23新增的std::views::join_with主要用于处理嵌套范围,但可以通过包装单个容器实现类似效果:

#include <vector>
#include <iostream>
#include <ranges>

int main() {
    std::vector<int> vec1{0,1,2};
    std::vector<int> vec2{3,4,5};

    auto concatenated = std::views::single(vec1) | std::views::join_with(vec2);
    for (const auto& e : concatenated){
        std::cout << e << ", ";
    }
    return 0;
}

这种写法不如专门的拼接视图直观,优先级低于前两种方案。


内容的提问来源于stack exchange,提问作者vlad_tepesch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 08:47:42