Saya mendapati diri saya menulis ini beberapa saat yang lalu:
template <long int T_begin, long int T_end>
class range_class {
public:
class iterator {
friend class range_class;
public:
long int operator *() const { return i_; }
const iterator &operator ++() { ++i_; return *this; }
iterator operator ++(int) { iterator copy(*this); ++i_; return copy; }
bool operator ==(const iterator &other) const { return i_ == other.i_; }
bool operator !=(const iterator &other) const { return i_ != other.i_; }
protected:
iterator(long int start) : i_ (start) { }
private:
unsigned long i_;
};
iterator begin() const { return iterator(T_begin); }
iterator end() const { return iterator(T_end); }
};
template <long int T_begin, long int T_end>
const range_class<T_begin, T_end>
range()
{
return range_class<T_begin, T_end>();
}
Dan ini memungkinkan saya untuk menulis hal-hal seperti ini:
for (auto i: range<0, 10>()) {
// stuff with i
}
Sekarang, saya tahu apa yang saya tulis mungkin bukan kode terbaik. Dan mungkin ada cara untuk membuatnya lebih fleksibel dan berguna. Tapi bagi saya sepertinya sesuatu seperti ini seharusnya dijadikan bagian dari standar.
Jadi begitu? Apakah semacam pustaka baru ditambahkan untuk iterator melalui rentang bilangan bulat, atau mungkin rentang umum nilai skalar yang dihitung?
range
fungsi template? Itu tidak menambahkan apa pun ke penggunaan yangrange_class
digunakan. Maksudku,range<0,10>()
danrange_class<0,10>()
terlihat persis sama!Jawaban:
Pustaka standar C ++ tidak memilikinya, tetapi Boost.Range memiliki boost :: count_range , yang tentunya memenuhi syarat. Anda juga bisa menggunakan boost :: irange , yang sedikit lebih fokus dalam cakupannya.
Pustaka rentang C ++ 20 akan memungkinkan Anda melakukan ini melalui
view::iota(start, end)
.sumber
std::experimental::ranges
namespace.range-v3
selalu semacam implementasi referensi yang akan saya katakan. Tapi sekarang saya percaya hal-hal dasar juga baru-baru ini telah dipilih ke dalam C ++ 20, jadi kami akanstd::
segera mendapatkannya! :-)Sejauh yang saya tahu, tidak ada kelas seperti itu di C ++ 11.
Bagaimanapun, saya mencoba meningkatkan penerapan Anda. Saya membuatnya non-template , karena saya tidak melihat ada keuntungan dalam membuatnya template . Sebaliknya, ini memiliki satu kelemahan utama: bahwa Anda tidak dapat membuat rentang pada waktu proses, karena Anda perlu mengetahui argumen template pada waktu kompilasi itu sendiri.
Ini kodenya:
Kode tes:
Keluaran:
10 11 12 13 14 15 16 17 18 19
Demo onine .
sumber
iterator
untukconst_iterator
, memilikiiterator
berasal daristd::iterator
dan memilikirange
menerapkancbegin
dancend
. Oh dan ... mengapaiterator::operator++
mengembalikan referensi const ?[begin, end)
. @OP: +1 untuk permainan kata-kata pada putaran berbasis jangkauan yang bukan permainan kata-kata :-)v++
yang seharusnya mengembalikan nilai sebelum operasi kenaikan terjadi. Saya menyarankan Anda untuk menjelajahi perbedaan antara++i
dan dii++
manai
dinyatakanint
.Saya menulis perpustakaan yang disebut
range
untuk tujuan yang persis sama kecuali itu adalah rentang waktu berjalan, dan ide dalam kasus saya berasal dari Python. Saya menganggap versi waktu kompilasi, tetapi menurut pendapat saya yang sederhana, tidak ada keuntungan nyata untuk mendapatkan versi waktu kompilasi. Anda dapat menemukan pustaka tersebut di bitbucket, dan pustaka itu berada di bawah Lisensi Boost: Range . Ini adalah pustaka satu tajuk, kompatibel dengan C ++ 03 dan berfungsi seperti pesona dengan loop berbasis rentang di C ++ 11 :)Fitur :
Wadah akses acak sejati dengan semua lonceng dan peluit!
Rentang dapat dibandingkan secara leksikografis.
Dua fungsi
exist
(mengembalikan bool), danfind
(mengembalikan iterator) untuk memeriksa keberadaan angka.Perpustakaan diuji unit menggunakan CATCH .
Contoh penggunaan dasar, bekerja dengan kontainer standar, bekerja dengan algoritme standar, dan bekerja dengan loop berbasis rentang.
Berikut adalah pengantar satu menit . Akhirnya, saya menyambut baik saran tentang perpustakaan kecil ini.
sumber
Saya menemukan bahwa
boost::irange
itu jauh lebih lambat daripada loop integer kanonik. Jadi saya menetapkan solusi yang jauh lebih sederhana berikut menggunakan makro preprocessor:Kemudian Anda dapat melakukan loop seperti ini:
Kisaran ini secara otomatis dimulai dari nol. Ini dapat dengan mudah diperpanjang untuk memulai dari nomor tertentu.
sumber
for (RANGE(i, flag? n1: n2))
akan memberikan hasil yang mengejutkan, karena Anda gagal mengikuti salah satu Aturan Dasar Makro Non-Jahat, yaitu mengurung semua parameter Anda (termasuk, dalam hal ini,b
). Pendekatan Anda juga tidak memberikan manfaat kinerja apa pun dibandingkan non-makro, pendekatan berbasis "objek jangkauan" (mis . Jawaban Nawaz ).Ini adalah formulir sederhana yang bekerja dengan baik untuk saya. Apakah ada risiko dalam pendekatan saya?
r_iterator
adalah tipe yang berperilaku, sebanyak mungkin, seperti along int
. Oleh karena itu banyak operator seperti==
dan++
, cukup melewati kelong int
. Saya 'mengekspos' int panjang yang mendasari melaluioperator long int
danoperator long int &
konversi.( Sunting: - kita dapat membuat metode
range
statis daripada const.)sumber
Ini mungkin sedikit terlambat tetapi saya baru saja melihat pertanyaan ini dan saya telah menggunakan kelas ini untuk sementara waktu sekarang:
Penggunaan:
sumber
sudahkah kamu mencoba menggunakan
Sebagian besar waktu sesuai dengan tagihan.
Misalnya
Perhatikan bahwa printInt dapat OFC diganti dengan lambda di C ++ 0x. Juga satu variasi kecil dari penggunaan ini (hanya untuk random_iterator)
Hanya untuk iterator Fwd
sumber
Anda dapat dengan mudah membuat urutan yang meningkat di C ++ 11 menggunakan std :: iota ():
sumber
range
kelas akan memodelkan jangkauan. Bagaimanapun Anda sedang membangunnya. Itu adalah pemborosan memori dan akses memori. Solusinya sangat redundan, karena vektor tidak menyimpan informasi nyata kecuali jumlah elemen dan nilai elemen pertama (jika ada).