Đối với bất kỳ ai thích std::views::iota
câu trả lời của Cigien nhưng không hoạt động trong C ++ 20 trở lên, việc triển khai phiên bản std::views::iota
tương thích đơn giản và nhẹ sẽ khá dễ dàngc ++ 11 hoặc ở trên.
Tất cả những gì nó yêu cầu là:
- Loại " LegacyInputIterator " cơ bản (thứ xác định
operator++
và operator*
) bao bọc một giá trị tích phân (ví dụ: an int
)
- Một số lớp giống như "phạm vi" có
begin()
và end()
trả về các trình vòng lặp ở trên. Điều này sẽ cho phép nó hoạt động trong các for
vòng lặp dựa trên phạm vi
Một phiên bản đơn giản của điều này có thể là:
#include <iterator>
class counting_iterator
{
public:
using iterator_category = std::input_iterator_tag;
using value_type = int;
using reference = int;
using pointer = int*;
using difference_type = std::ptrdiff_t;
constexpr explicit counting_iterator(int x) : m_value{x}{}
constexpr counting_iterator(const counting_iterator&) = default;
constexpr counting_iterator& operator=(const counting_iterator&) = default;
constexpr reference operator*() const { return m_value; }
constexpr pointer operator->() const { return &m_value; }
constexpr counting_iterator& operator++() {
m_value++;
return (*this);
}
constexpr counting_iterator operator++(int) {
const auto copy = (*this);
++(*this);
return copy;
}
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;
};
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}; }
};
constexpr iota_range iota(int first, int last)
{
return iota_range{first, last};
}
Tôi đã xác định ở trên với constexpr
nơi nó được hỗ trợ, nhưng đối với các phiên bản C ++ trước đó như C ++ 11/14, bạn có thể cần phải loại bỏ constexpr
nơi không hợp pháp trong các phiên bản đó để làm như vậy.
Bảng mẫu trên cho phép mã sau hoạt động trong phiên bản trước C ++ 20:
for (int const i : iota(0, 10))
{
std::cout << i << " ";
i = 42;
}
Điều này sẽ tạo ra cùng một assembly với std::views::iota
giải pháp C ++ 20 và for
giải pháp -loop cổ điển khi được tối ưu hóa.
Điều này hoạt động với bất kỳ trình biên dịch tuân thủ C ++ 11 nào (ví dụ như trình biên dịch như vậy gcc-4.9.4
) và vẫn tạo ra một hợp ngữ gần giống với một for
đối tác -loop cơ bản .
Lưu ý: Hàm iota
trợ giúp chỉ dành cho tính năng tương đương với std::views::iota
giải pháp C ++ 20 ; nhưng trên thực tế, bạn cũng có thể trực tiếp tạo một iota_range{...}
thay vì gọi iota(...)
. Phần trước chỉ trình bày một đường dẫn nâng cấp dễ dàng nếu người dùng muốn chuyển sang C ++ 20 trong tương lai.