如何在基于范围的for循环中找到当前对象的索引?

新手上路,请多包涵

假设我有以下代码:

 vector<int> list;
for(auto& elem:list) {
    int i = elem;
}

我可以在向量中找到 elem 的位置而不维护单独的迭代器吗?

原文由 Fred Finkle 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
1 个回答

这是一个使用 c++20 的非常漂亮的解决方案:

 #include <array>
#include <iostream>
#include <ranges>

template<typename T>
struct EnumeratedElement {
    std::size_t index;
    T& element;
};

auto enumerate(std::ranges::range auto& range)
    -> std::ranges::view auto
{
    return range | std::views::transform(
        [i = std::size_t{}](auto& element) mutable {
            return EnumeratedElement{i++, element};
        }
    );
}

auto main() -> int {
    auto const elements = std::array{3, 1, 4, 1, 5, 9, 2};
    for (auto const [index, element] : enumerate(elements)) {
        std::cout << "Element " << index << ": " << element << '\n';
    }
}

这里使用的主要特性是 c++20 范围、c++20 概念、c++11 可变 lambda、c++14 lambda 捕获初始化程序和 c++17 结构化绑定。有关任何这些主题的信息,请参阅 cppreference.com。

请注意,结构化绑定中的 element 实际上是引用而不是元素的副本(此处无关紧要)。这是因为 auto 周围的任何限定符只会影响从中提取字段的临时对象,而不影响字段本身。

生成的代码与由此生成的代码相同(至少由 gcc 10.2 生成):

 #include <array>
#include <iostream>
#include <ranges>

auto main() -> int {
    auto const elements = std::array{3, 1, 4, 1, 5, 9, 2};
    for (auto index = std::size_t{}; auto& element : elements) {
        std::cout << "Element " << index << ": " << element << '\n';
        index++;
    }
}

证明: https ://godbolt.org/z/a5bfxz

原文由 Björn Sundin 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题