Saya membuat koleksi yang ingin saya berikan iterator acak gaya STL. Saya mencari-cari contoh implementasi iterator tapi saya tidak menemukannya. Saya tahu tentang perlunya overload const []
dan *
operator. Apa persyaratan untuk iterator untuk menjadi "STL-style" dan apa beberapa perangkap lain yang harus dihindari (jika ada)?
Konteks tambahan: Ini untuk perpustakaan dan saya tidak ingin memperkenalkan ketergantungan padanya kecuali saya benar-benar perlu. Saya menulis koleksi saya sendiri untuk dapat memberikan kompatibilitas biner antara C ++ 03 dan C ++ 11 dengan kompiler yang sama (jadi tidak ada STL yang mungkin akan rusak).
c++
iterator
const-iterator
Tamás Szelei
sumber
sumber
Jawaban:
http://www.cplusplus.com/reference/std/iterator/ memiliki bagan praktis yang merinci spesifikasi § 24.2.2 dari standar C ++ 11. Pada dasarnya, iterator memiliki tag yang menggambarkan operasi yang valid, dan tag memiliki hierarki. Di bawah ini murni simbolis, kelas-kelas ini sebenarnya tidak ada.
Anda dapat mengkhususkan
std::iterator_traits<youriterator>
, atau memasukkan typedef yang sama di iterator itu sendiri, atau mewarisi daristd::iterator
(yang memiliki typedef ini). Saya lebih suka opsi kedua, untuk menghindari mengubah hal-hal distd
namespace, dan untuk keterbacaan, tetapi kebanyakan orang mewarisi daristd::iterator
.Perhatikan iterator_category harus menjadi salah satu
std::input_iterator_tag
,std::output_iterator_tag
,std::forward_iterator_tag
,std::bidirectional_iterator_tag
, ataustd::random_access_iterator_tag
, tergantung pada kebutuhan iterator Anda memenuhi. Tergantung pada iterator Anda, Anda dapat memilih untuk mengkhususkanstd::next
,std::prev
,std::advance
, danstd::distance
juga, tapi ini jarang diperlukan. Dalam kasus yang sangat jarang Anda mungkin ingin mengkhususkanstd::begin
danstd::end
.Wadah Anda mungkin juga harus memiliki
const_iterator
, yang merupakan iterator (mungkin bisa diubah) untuk data konstan yang serupa dengan Anda,iterator
kecuali itu harus dibangun secara implisit dari aiterator
dan pengguna tidak dapat memodifikasi data. Adalah umum untuk pointer internal untuk menjadi pointer ke data yang tidak konstan, dan telahiterator
diwarisiconst_iterator
untuk meminimalkan duplikasi kode.Posting saya di Menulis Wadah Anda sendiri memiliki prototipe wadah / iterator yang lebih lengkap.
sumber
std::iterator_traits
atau menentukan sendiri typedefs, Anda juga bisa hanya berasal daristd::iterator
, yang mendefinisikannya untuk Anda, tergantung pada parameter templatnya.const_iterator
. Apa lagi yang kurang dari posting saya? Anda tampaknya menyiratkan ada lebih banyak yang ditambahkan ke kelas, tetapi pertanyaannya adalah secara khusus tentang mengimplementasikan iterator.std::iterator
itu diusulkan untuk usang dalam C ++ 17 ; tidak, tapi saya tidak akan menyimpannya di sekitar untuk waktu yang lama.std::iterator
sudah tidak digunakan lagi.operator bool
sangat berbahaya. Seseorang akan mencoba menggunakannya untuk mendeteksi akhir rentangwhile(it++)
, tetapi yang benar-benar diperiksa adalah apakah iterator dibangun dengan parameter.The dokumentasi iterator_facade dari Boost.Iterator memberikan apa yang tampak seperti tutorial yang bagus pada pelaksanaan iterator untuk linked list. Bisakah Anda menggunakannya sebagai titik awal untuk membangun iterator akses-acak di atas wadah Anda?
Jika tidak ada yang lain, Anda dapat melihat fungsi anggota dan mengetik yang disediakan oleh
iterator_facade
dan menggunakannya sebagai titik awal untuk membangun Anda sendiri.sumber
Thomas Becker menulis artikel yang bermanfaat tentang masalah ini di sini .
Ada juga pendekatan ini (mungkin lebih sederhana) yang muncul sebelumnya pada SO: Bagaimana cara mengimplementasikan iterators dan const_iterators kustom?
sumber
Berikut adalah contoh iterator penunjuk mentah.
Anda seharusnya tidak menggunakan kelas iterator untuk bekerja dengan pointer mentah!
Solusi lingkaran berbasis rentang pointer mentah. Tolong, koreksi saya, jika ada cara yang lebih baik untuk membuat loop berbasis rentang dari pointer mentah.
Dan tes sederhana
sumber
Pertama-tama, Anda dapat mencari di sini daftar berbagai operasi yang perlu didukung jenis iterator individual.
Selanjutnya, ketika Anda telah membuat kelas iterator Anda, Anda perlu mengkhususkan diri
std::iterator_traits
untuk itu dan memberikan beberapa yang diperlukantypedef
(sepertiiterator_category
atauvalue_type
) atau sebagai alternatifstd::iterator
, yang mendefinisikan yang diperlukantypedef
untuk Anda dan karena itu dapat digunakan dengan defaultstd::iterator_traits
.Penafian: Saya tahu beberapa orang tidak begitu suka
cplusplus.com
, tetapi mereka memberikan beberapa informasi yang sangat berguna tentang ini.sumber
Saya berada di kapal yang sama dengan Anda karena alasan yang berbeda (sebagian pendidikan, sebagian kendala). Saya harus menulis ulang semua wadah perpustakaan standar dan wadah harus sesuai dengan standar. Itu berarti, jika saya menukar wadah saya dengan versi stl , kodenya akan bekerja sama. Yang juga berarti saya harus menulis ulang iterators.
Bagaimanapun, saya melihat EASTL . Selain belajar banyak tentang wadah yang saya tidak pernah pelajari selama ini menggunakan wadah stl atau melalui program sarjana saya. Alasan utama adalah bahwa EASTL lebih mudah dibaca daripada rekan stl (saya menemukan ini hanya karena kurangnya semua makro dan gaya pengkodean lurus ke depan). Ada beberapa hal yang menjijikkan di sana (seperti # ifdefs untuk pengecualian) tetapi tidak ada yang membuat Anda kewalahan.
Seperti yang disebutkan orang lain, lihat referensi cplusplus.com tentang iterator dan wadah.
sumber
Saya sedang mencoba untuk memecahkan masalah untuk dapat mengulangi beberapa array teks yang berbeda yang semuanya disimpan dalam database memori yang besar
struct
.Berikut ini dikerjakan menggunakan Visual Studio 2017 Community Edition pada aplikasi tes MFC. Saya memasukkan ini sebagai contoh karena posting ini adalah salah satu dari beberapa yang saya temui yang memberikan bantuan namun masih kurang untuk kebutuhan saya.
Yang
struct
berisi data penduduk memori tampak seperti berikut ini. Saya telah menghapus sebagian besar elemen demi singkatnya dan juga belum termasuk definisi Preprocessor yang digunakan (SDK yang digunakan adalah untuk C serta C ++ dan sudah tua).Apa yang saya tertarik lakukan adalah memiliki iterator untuk berbagai
WCHAR
array dua dimensi yang berisi string teks untuk mnemonik.Pendekatan saat ini adalah dengan menggunakan templat untuk menentukan kelas proxy untuk setiap array dan kemudian memiliki kelas iterator tunggal yang dapat digunakan untuk beralih pada array tertentu dengan menggunakan objek proxy yang mewakili array.
Salinan data penduduk memori disimpan dalam objek yang menangani membaca dan menulis data penduduk memori dari / ke disk. Kelas ini,
CFilePara
berisi kelas proksi templated (MnemonicIteratorDimSize
dan sub kelas dari mana asalnya,MnemonicIteratorDimSizeBase
) dan kelas iteratorMnemonicIterator
,.Objek proxy yang dibuat dilampirkan ke objek iterator yang mengakses informasi yang diperlukan melalui antarmuka yang dijelaskan oleh kelas dasar dari mana semua kelas proxy diturunkan. Hasilnya adalah memiliki satu jenis kelas iterator yang dapat digunakan dengan beberapa kelas proxy yang berbeda karena semua kelas proxy yang berbeda mengekspos antarmuka yang sama, antarmuka kelas basis proxy.
Hal pertama adalah membuat seperangkat pengidentifikasi yang akan diberikan kepada pabrik kelas untuk menghasilkan objek proxy spesifik untuk jenis mnemonik tersebut. Pengidentifikasi ini digunakan sebagai bagian dari antarmuka pengguna untuk mengidentifikasi data penyediaan tertentu yang ingin dilihat pengguna dan mungkin dimodifikasi.
Kelas Proksi
Kelas proxy templated dan kelas dasarnya adalah sebagai berikut. Saya perlu mengakomodasi beberapa jenis
wchar_t
array string teks. Array dua dimensi memiliki jumlah mnemonik yang berbeda, tergantung pada jenis (tujuan) mnemonik dan tipe mnemonik yang berbeda memiliki panjang maksimum yang berbeda, bervariasi antara lima karakter teks dan dua puluh karakter teks. Templat untuk kelas proksi turunan sangat cocok dengan templat yang membutuhkan jumlah karakter maksimum di setiap mnemonik. Setelah objek proxy dibuat, kami kemudian menggunakanSetRange()
metode untuk menentukan array mnemonic aktual dan jangkauannya.Kelas Iterator
Kelas iterator itu sendiri adalah sebagai berikut. Kelas ini hanya menyediakan fungsionalitas iterator maju dasar yang diperlukan saat ini. Namun saya berharap ini akan berubah atau diperpanjang ketika saya membutuhkan sesuatu tambahan darinya.
Pabrik objek proxy menentukan objek mana yang akan dibuat berdasarkan pengidentifikasi mnemonik. Objek proxy dibuat dan penunjuk yang dikembalikan adalah tipe kelas dasar standar sehingga memiliki antarmuka yang seragam terlepas dari bagian mnemonik mana yang sedang diakses. The
SetRange()
metode yang digunakan untuk menentukan ke objek proxy elemen array tertentu proxy mewakili dan berbagai elemen array.Menggunakan Kelas Proxy dan Iterator
Kelas proxy dan iteratornya digunakan seperti yang ditunjukkan pada loop berikut untuk mengisi
CListCtrl
objek dengan daftar mnemonik. Saya menggunakanstd::unique_ptr
sehingga ketika kelas proxy saya tidak lagi diperlukan danstd::unique_ptr
keluar dari ruang lingkup, memori akan dibersihkan.Apa yang dilakukan kode sumber ini adalah membuat objek proxy untuk array di dalamnya
struct
yang sesuai dengan pengidentifikasi mnemonik yang ditentukan. Itu kemudian menciptakan iterator untuk objek itu, menggunakan rentangfor
untuk mengisiCListCtrl
kontrol dan kemudian membersihkan. Ini semua adalahwchar_t
string teks mentah yang mungkin persis jumlah elemen array sehingga kami menyalin string ke buffer sementara untuk memastikan bahwa teks tersebut dihentikan nol.sumber
Dan sekarang iterator kunci untuk rentang berbasis untuk loop.
Pemakaian:
Itu yang saya cari. Tapi sepertinya tidak ada yang memilikinya.
Anda mendapatkan keselarasan kode OCD saya sebagai bonus.
Sebagai latihan, tulis untuk Anda sendiri
values(my_map)
sumber