C ++ 11 menyediakan banyak cara untuk melakukan iterasi pada container. Sebagai contoh:
Loop berbasis rentang
for(auto c : container) fun(c)
std :: for_each
for_each(container.begin(),container.end(),fun)
Namun apa cara yang disarankan untuk mengulang lebih dari dua (atau lebih) wadah dengan ukuran yang sama untuk mencapai sesuatu seperti:
for(unsigned i = 0; i < containerA.size(); ++i) {
containerA[i] = containerB[i];
}
c++
c++11
iterator
containers
memec
sumber
sumber
transform
hadir di#include <algorithm>
?containerA = containerB;
sebagai pengganti pengulangan.Jawaban:
Agak terlambat ke pesta. Tapi: Saya akan mengulangi indeks. Tetapi tidak dengan
for
pengulangan klasik melainkan denganfor
pengulangan berbasis rentang di atas indeks:indices
adalah fungsi pembungkus sederhana yang mengembalikan rentang (dievaluasi secara malas) untuk indeks. Karena implementasinya - meskipun sederhana - agak terlalu lama untuk diposting di sini, Anda dapat menemukan implementasinya di GitHub .Kode ini seefisien menggunakan
for
loop manual dan klasik .Jika pola ini sering muncul dalam data Anda, pertimbangkan untuk menggunakan pola lain yang merupakan
zip
dua urutan dan menghasilkan berbagai tupel, sesuai dengan elemen yang dipasangkan:Implementasi
zip
dibiarkan sebagai latihan bagi pembaca, tetapi mengikuti dengan mudah dari implementasiindices
.(Sebelum C ++ 17 Anda harus menulis yang berikut ini :)
sumber
boost::counting_range(size_t(0), containerA.size())
indices
implementasi saya menghasilkan keluaran kompiler yang identik dengan menggunakanfor
loop manual . Tidak ada biaya tambahan apapun.Untuk contoh spesifik Anda, gunakan saja
Untuk kasus yang lebih umum, Anda dapat menggunakan Boost.Iterator
zip_iterator
, dengan fungsi kecil untuk membuatnya dapat digunakan dalam loop berbasis rentang. Untuk kebanyakan kasus, ini akan berhasil:Contoh langsung.
Namun, untuk genericity full-blown, Anda mungkin ingin sesuatu yang lebih seperti ini , yang akan bekerja dengan benar untuk array dan tipe user-defined yang tidak memiliki anggota
begin()
/end()
tapi jangan memilikibegin
/end
fungsi dalam namespace mereka. Selain itu, ini akan memungkinkan pengguna untuk secara khusus mendapatkanconst
akses melaluizip_c...
fungsi.Dan jika Anda seorang pendukung pesan kesalahan yang bagus, seperti saya, maka Anda mungkin menginginkan ini , yang memeriksa apakah ada wadah sementara yang diteruskan ke salah satu
zip_...
fungsi, dan mencetak pesan kesalahan yang bagus jika demikian.sumber
auto
bekerja persis sama dengan parameter template, danT&&
dalam template adalah referensi universal seperti yang dijelaskan di tautan pertama, jadiauto&& v = 42
akan disimpulkan sebagaiint&&
danauto&& w = v;
kemudian akan disimpulkan sebagaiint&
. Ini memungkinkan Anda untuk mencocokkan lvalues serta rvalues dan membiarkan keduanya bisa berubah, tanpa membuat salinan.zip_range
.Saya heran mengapa tidak ada yang menyebutkan ini:
PS: jika ukuran wadah tidak cocok, maka Anda harus memasukkan kode di dalam pernyataan if.
sumber
Ada banyak cara untuk melakukan hal - hal tertentu dengan banyak penampung seperti yang disediakan di
algorithm
tajuk. Misalnya, dalam contoh yang Anda berikan, Anda dapat menggunakanstd::copy
for loop sebagai pengganti eksplisit.Di sisi lain, tidak ada cara built-in untuk secara umum mengulang beberapa kontainer selain for loop normal. Ini tidak mengherankan karena ada banyak cara untuk mengulang. Pikirkan tentang hal ini: Anda dapat mengulangi satu wadah dengan satu langkah, satu wadah dengan langkah lainnya; atau melalui satu wadah hingga mencapai ujung kemudian mulai memasukkan sementara Anda melewati ke ujung wadah lainnya; atau satu langkah dari wadah pertama untuk setiap kali Anda benar-benar melewati wadah lainnya, lalu mulai lagi; atau pola lainnya; atau lebih dari dua wadah sekaligus; dll ...
Namun, jika Anda ingin membuat fungsi gaya "for_each" Anda sendiri yang melakukan iterasi melalui dua penampung hanya sampai penampung yang paling pendek, Anda dapat melakukan sesuatu seperti ini:
Tentunya Anda dapat membuat strategi iterasi apa pun yang Anda inginkan dengan cara yang serupa.
Tentu saja, Anda mungkin berpendapat bahwa melakukan perulangan for dalam secara langsung lebih mudah daripada menulis fungsi khusus seperti ini ... dan Anda akan benar, jika Anda hanya akan melakukannya satu atau dua kali. Tetapi hal yang menyenangkan adalah ini sangat dapat digunakan kembali. =)
sumber
for (Container1::iterator i1 = c1.begin(), Container2::iterator i2 = c2.begin(); (i1 != end1) && (i2 != end2); ++it1, ++i2)
tetapi penyusun berteriak. Adakah yang bisa menjelaskan mengapa ini tidak valid?for (int x = 0, y = 0; ...
berhasil, tetapifor (int x = 0, double y = 0; ...)
tidak.typename...
Jika Anda perlu mengulang secara bersamaan melalui 2 penampung saja, ada versi tambahan dari algoritme for_each standar di pustaka rentang peningkatan, misalnya:
Saat Anda perlu menangani lebih dari 2 kontainer dalam satu algoritme, Anda harus bermain dengan zip.
sumber
solusi lain dapat menangkap referensi dari iterator wadah lain dalam lambda dan menggunakan operator kenaikan pos di atasnya. misalnya salinan sederhana adalah:
di dalam lambda Anda dapat melakukan apa saja dengan
ita
dan kemudian menaikkannya. Ini dengan mudah meluas ke beberapa wadah kontainer.sumber
Pustaka rentang menyediakan fungsi ini dan fungsi lain yang sangat membantu. Contoh berikut menggunakan Boost.Range . Rangev3 Eric Niebler seharusnya menjadi alternatif yang baik.
C ++ 17 akan membuatnya lebih baik dengan binding terstruktur:
sumber
delme.cxx:15:25: error: no match for 'operator=' (operand types are 'std::tuple<int&, char&>' and 'const boost::tuples::cons<const int&, boost::tuples::cons<const char&, boost::tuples::null_type> >') std::tie(ti,tc) = i;
^19.13.26132.0
versi MSVC dan Windows SDK10.0.16299.0
):error C2679: binary '<<': no operator found which takes a right-hand operand of type 'const boost::tuples::cons<const char &,boost::fusion::detail::build_tuple_cons<boost::fusion::single_view_iterator<Sequence,boost::mpl::int_<1>>,Last,true>::type>' (or there is no acceptable conversion)
boost::combine
: stackoverflow.com/q/55585723/8414561Saya sedikit terlambat; tetapi Anda dapat menggunakan ini (fungsi variadic gaya-C):
atau ini (menggunakan paket parameter fungsi):
atau ini (menggunakan daftar penginisialisasi tertutup kurung kurawal):
atau Anda dapat menggabungkan vektor seperti di sini: Apa cara terbaik untuk menggabungkan dua vektor? dan kemudian melakukan iterasi pada vektor besar.
sumber
Ini satu varian
Contoh penggunaan
sumber