Bagi siapa pun yang menyukai jawaban std::views::iota
Cigien tetapi tidak bekerja di C++20 atau lebih tinggi, cukup mudah untuk mengimplementasikan versi sederhana dan ringan dari kelas std::views::iota ="post-tag" title="tampilkan pertanyaan yang diberi tag 'c++11'" rel="tag">c++11 atau lebih tinggi.
Yang diperlukan hanyalah:
- Tipe dasar LegacyInputIterator (sesuatu yang mendefinisikan
operator++
dan operator*
) yang membungkus nilai integral (misalnya int
)
- Beberapa kelas seperti rentang yang memiliki
begin()
dan end()
yang mengembalikan iterator di atas. Ini akan memungkinkannya bekerja dalam loop for
berbasis rentang
Versi sederhananya bisa berupa:
#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};
}
Saya telah mendefinisikan hal di atas dengan constexpr
jika didukung, tetapi untuk versi C++ sebelumnya seperti C++11/14, Anda mungkin perlu menghapus constexpr
jika versi tersebut tidak sah untuk melakukannya.
Boilerplate di atas memungkinkan kode berikut berfungsi di pra-C++20:
for (int const i : iota(0, 10))
{
std::cout << i << " "; // ok
i = 42; // error
}
Yang akan menghasilkan perakitan yang sama dengan solusi C++20 std::views::iota
dan solusi for
-loop klasik ketika dioptimalkan.
Ini berfungsi dengan semua kompiler yang mendukung C++11 (misalnya kompiler seperti gcc-4.9.4
) dan masih menghasilkan perakitan yang hampir identik ke rekanan for
-loop dasar.
Catatan: Fungsi pembantu iota
hanya untuk paritas fitur dengan solusi C++20 std::views::iota
; namun secara realistis, Anda juga dapat langsung membuat iota_range{...}
alih-alih memanggil iota(...)
. Yang pertama hanya menyajikan jalur peningkatan yang mudah jika pengguna ingin beralih ke C++20 di masa mendatang.
person
Human-Compiler
schedule
13.08.2020
while(i_copy = loop()) { }
- person stark   schedule 13.08.2020const int& i_safe = i
. Kompiler Anda harus menghindari tipuan apa pun. - person Brian   schedule 13.08.2020i
rentan terhadap badan loop jahat. - person stark   schedule 13.08.2020i
tidak baik? Anda ingin memiliki akses hanya baca kei
di loop? - person cigien   schedule 13.08.2020for({int i=0; i<10; ++i}){
untuk hal ini, tetapi tidak pernah memiliki keberanian untuk menyarankannya kepada komite standar, atau kepada Bjarne ketika dia melakukan pekerjaan jujurnya sehari-hari di Morgan Stanley. Tentu saja saran saya tidak mengizinkan Anda mengaksesi
di badan. - person Bathsheba   schedule 13.08.2020const int i
. Mutabilitas indeks hanya diekspos jika diperlukan dan Anda dapat menggunakan kata kunciinline
untuk membuatnya tidak berpengaruh pada keluaran yang dikompilasi. - person Monty Thibault   schedule 14.08.2020const
untuk memulai. - person Konrad Rudolph   schedule 16.08.2020ì
diubah dalam loop. Jika loop Anda besar, maka loop tersebut harus difaktorkan ulang menjadi sebuah fungsi. - person Phil1970   schedule 17.08.2020