对于喜欢 Cigien 的 std::views::iota 答案但不在 C++20 或更高版本中工作的任何人,实现std::views::iota 兼容c++11 或更高版本的简化和轻量级版本相当简单。
只需要:
- 一种基本的“LegacyInputIterator”类型(定义
operator++ 和operator*),它包含一个整数值(例如int)
- 一些具有
begin() 和end() 的类“范围”类返回上述迭代器。这将允许它在基于范围的for 循环中工作
一个简化的版本可能是:
#include <iterator>
// This is just a class that wraps an 'int' in an iterator abstraction
// Comparisons compare the underlying value, and 'operator++' just
// increments the underlying int
class counting_iterator
{
public:
// basic iterator boilerplate
using iterator_category = std::input_iterator_tag;
using value_type = int;
using reference = int;
using pointer = int*;
using difference_type = std::ptrdiff_t;
// Constructor / assignment
constexpr explicit counting_iterator(int x) : m_value{x}{}
constexpr counting_iterator(const counting_iterator&) = default;
constexpr counting_iterator& operator=(const counting_iterator&) = default;
// "Dereference" (just returns the underlying value)
constexpr reference operator*() const { return m_value; }
constexpr pointer operator->() const { return &m_value; }
// Advancing iterator (just increments the value)
constexpr counting_iterator& operator++() {
m_value++;
return (*this);
}
constexpr counting_iterator operator++(int) {
const auto copy = (*this);
++(*this);
return copy;
}
// Comparison
constexpr bool operator==(const counting_iterator& other) const noexcept {
return m_value == other.m_value;
}
constexpr bool operator!=(const counting_iterator& other) const noexcept {
return m_value != other.m_value;
}
private:
int m_value;
};
// Just a holder type that defines 'begin' and 'end' for
// range-based iteration. This holds the first and last element
// (start and end of the range)
// The begin iterator is made from the first value, and the
// end iterator is made from the second value.
struct iota_range
{
int first;
int last;
constexpr counting_iterator begin() const { return counting_iterator{first}; }
constexpr counting_iterator end() const { return counting_iterator{last}; }
};
// A simple helper function to return the range
// This function isn't strictly necessary, you could just construct
// the 'iota_range' directly
constexpr iota_range iota(int first, int last)
{
return iota_range{first, last};
}
我已经用 constexpr 定义了上面的内容,但对于 C++ 的早期版本,如 C++11/14,您可能需要删除 constexpr,因为在这些版本中这样做是不合法的.
上述样板文件使以下代码能够在 C++20 之前的版本中工作:
for (int const i : iota(0, 10))
{
std::cout << i << " "; // ok
i = 42; // error
}
优化后将生成 same assembly 作为 C++20 std::views::iota 解决方案和经典 for-loop 解决方案。
这适用于任何符合 C++11 的编译器(例如像 gcc-4.9.4 这样的编译器),并且仍然会生成 nearly identical assembly 到基本的 for 循环对应项。
注意: iota 辅助函数仅用于与 C++20 std::views::iota 解决方案进行功能奇偶校验;但实际上,您也可以直接构造一个iota_range{...},而不是调用iota(...)。如果用户希望将来切换到 C++20,前者只是提供了一个简单的升级路径。