Cigien en seven herkes için std::views::iota
bir cevap ancak yukarıda C ++ 20 çalışıp çalışmadığını, bu basitleştirilmiş ve hafif sürümünü uygulamak için oldukça basittir std::views::iota
uyumluc ++ 11 ya da üzerinde.
Tek gereken şudur:
- Bir integral değeri (ör. Bir ) saran temel bir " LegacyInputIterator " türü (
operator++
ve tanımlayan bir şey )operator*
int
- Yukarıdaki yineleyicileri olan
begin()
ve end()
döndüren bazı "aralık" benzeri sınıflar . Bu, menzile dayalı for
döngülerde çalışmasına izin verecektir.
Bunun basitleştirilmiş bir versiyonu şunlar olabilir:
#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};
}
Yukarıdakileri constexpr
desteklendiği yerle tanımladım , ancak C ++ 11/14 gibi önceki C ++ constexpr
sürümleri için, bunu yapmak için bu sürümlerde yasal olmayan yerleri kaldırmanız gerekebilir .
Yukarıdaki standart şablon, aşağıdaki kodun C ++ 20 öncesi ile çalışmasını sağlar:
for (int const i : iota(0, 10))
{
std::cout << i << " ";
i = 42;
}
Optimize edildiğinde C ++ 20 çözümü ve klasik döngü çözümü ile aynı montajı üretecektir .std::views::iota
for
Bu, herhangi bir C ++ 11 uyumlu derleyici ile çalışır (örneğin, derleyiciler gibi gcc-4.9.4
) ve yine de temel bir döngü karşılığı ile neredeyse aynı derlemeyi üretir for
.
Not:iota
yardımcı fonksiyon sadece C ++ 20 özellik parite için std::views::iota
çözelti; ama gerçekçi olarak, aramak iota_range{...}
yerine doğrudan bir de oluşturabilirsiniz iota(...)
. İlki, bir kullanıcı gelecekte C ++ 20'ye geçmek isterse kolay bir yükseltme yolu sunar.