基于范围的 for 循环:迭代用一个元素扩展的向量

ger*_*ion 1 c++ iterator for-loop range

我想在 C++ 中实现与此 Python 代码相同的更少(但内存效率更高):

a = [1, 5, 3]
additional = 6
for elem in [additional] + a:
    print(elem) # prints: 6 1 5 3

# alternative without creating the additional vector:
import itertools
for elem in itertools.chain([additional], a):
    print(elem)
Run Code Online (Sandbox Code Playgroud)

我知道在 C++ 中这样做的唯一方法是:

#include <iostream>
#include <vector>

int main() {
        std::vector<int> a = {1, 5, 3};
        int additional = 6;

        for (int i = 0; i < a.size() + 1; ++i) {
                int cur_elem;
                if (i == 0) {
                        cur_elem = additional;
                } else {
                        cur_elem = a[i-1];
                }
                std::cout << cur_elem << std::endl;
        }
}
Run Code Online (Sandbox Code Playgroud)

有没有办法用基于范围的 for 循环来做到这一点?我找到了 Boost join 运算符,但它似乎只使用可迭代对象,所以我需要创建一个额外的向量(如 Python 示例中所示)。

理想情况下,迭代不会在内存中创建连接对象并使用标准库的算法。

Cás*_*nan 6

可以使用即将推出的范围功能来完成。

这是使用 Eric Nieblerrange-v3库的示例:

#include <iostream>
#include <vector>

#include <range/v3/view/concat.hpp>
#include <range/v3/view/single.hpp>

int main() {
    std::vector<int> a = {1, 5, 3};
    int additional = 6;
    for (auto i : ranges::concat_view(ranges::single_view{additional}, a)) {
        std::cout << i;
    }
}
Run Code Online (Sandbox Code Playgroud)

现场看!

通过使用视图,所有迭代器操作都是惰性的,并且不使用额外的内存(例如:不创建额外的向量/数组)

或者,没有for循环:

ranges::copy(ranges::concat_view(ranges::single_view{additional}, a), ranges::make_ostream_joiner(std::cout, ","));
Run Code Online (Sandbox Code Playgroud)

现场看!

(老实说,我更喜欢这个for版本,不过)

符合标准的解决方案

上面的解决方案有一个小问题:concat_view没有进入 C++20。如果您想要一个严格兼容的解决方案,您可能需要创建自己的版本,或者join_view改用:

#include <iostream>
#include <vector>

#include <ranges>

int main() {
    std::vector<int> a = {1, 5, 3};
    int additional = 6;

    std::vector v{{additional}, a};

    for(int i : std::ranges::join_view{v}) {
        std::cout << i;
    }
}
Run Code Online (Sandbox Code Playgroud)