Apakah ada adaptor wadah yang akan membalikkan arah iterator sehingga saya dapat beralih di atas wadah secara terbalik dengan range-for-loop berbasis?
Dengan iterator eksplisit saya akan mengonversi ini:
for (auto i = c.begin(); i != c.end(); ++i) { ...
dalam hal ini:
for (auto i = c.rbegin(); i != c.rend(); ++i) { ...
Saya ingin mengonversi ini:
for (auto& i: c) { ...
untuk ini:
for (auto& i: std::magic_reverse_adapter(c)) { ...
Apakah ada hal seperti itu atau saya harus menulisnya sendiri?
c++
c++11
ranged-loops
Alex B
sumber
sumber
begin
keend
, atau untuk berurusan dengan iterator aliran dan sejenisnya. Algoritme rentang akan menjadi besar, tetapi mereka benar-benar hanya gula sintaksis (kecuali untuk kemungkinan evaluasi malas) atas algoritma iterator.template<typename T> class reverse_adapter { public: reverse_adapter(T& c) : c(c) { } typename T::reverse_iterator begin() { return c.rbegin(); } typename T::reverse_iterator end() { return c.rend(); } private: T& c; };
Dapat ditingkatkan (menambahkanconst
versi, dll) tetapi berfungsi:vector<int> v {1, 2, 3}; reverse_adapter<decltype(v)> ra; for (auto& i : ra) cout << i;
mencetak321
template<typename T> reverse_adapter<T> reverse_adapt_container(T &c) {return reverse_adapter<T>(c);}
Jadi Anda bisa menggunakannyafor(auto &i: reverse_adapt_container(v)) cout << i;
untuk beralih.parallel_for
akan terjadi, dengan kondisi "Saya tidak peduli urutan apa" yang lebih kuat, jika dimasukkan ke dalam standar dalam beberapa bentuk. Tentu saja bisa memiliki gula sintaksis berbasis rentang juga :-)Jawaban:
Sebenarnya Meningkatkan memang memiliki adaptor seperti:
boost::adaptors::reverse
.sumber
Sebenarnya, dalam C ++ 14 dapat dilakukan dengan beberapa baris kode.
Ini adalah ide yang sangat mirip dengan solusi @ Paul. Karena hal-hal yang hilang dari C ++ 11, solusi itu agak tidak perlu membengkak (ditambah mendefinisikan bau std). Berkat C ++ 14 kita bisa membuatnya lebih mudah dibaca.
Pengamatan utama adalah bahwa for-loop berbasis rentang bekerja dengan mengandalkan
begin()
danend()
untuk memperoleh iterator kisaran. Berkat ADL , seseorang bahkan tidak perlu mendefinisikan kebiasaan merekabegin()
danend()
di std :: namespace.Berikut ini adalah solusi sampel yang sangat sederhana:
Ini berfungsi seperti mantra, misalnya:
mencetak seperti yang diharapkan
CATATAN
std::rbegin()
,,std::rend()
danstd::make_reverse_iterator()
belum diimplementasikan dalam GCC-4.9. Saya menulis contoh-contoh ini sesuai dengan standar, tetapi mereka tidak dapat dikompilasi di g stabil ++. Meskipun demikian, menambahkan bertopik sementara untuk ketiga fungsi ini sangat mudah. Berikut ini adalah contoh implementasi, jelas tidak lengkap tetapi berfungsi cukup baik untuk sebagian besar kasus:sumber
forward<T>
Andareverse
.using namespace std
di header, yang bukan ide yang baik. Atau apakah saya melewatkan sesuatu?Ini harus bekerja di C ++ 11 tanpa dorongan:
sumber
std
namespace memiliki perilaku yang tidak ditentukan per 17.6.4.2.1.make_reverse_iterator
tidak ada dalamstd
namespace, sehingga tidak akan berbenturan dengan versi C ++ 14 itu.Apakah ini Bekerja untukmu:
sumber
misalnya:
sumber
Jika Anda dapat menggunakan rentang v3 , Anda dapat menggunakan adaptor rentang terbalik
ranges::view::reverse
yang memungkinkan Anda melihat wadah secara terbalik.Contoh kerja minimal:
Lihat DEMO 1 .
Catatan: Sesuai Eric Niebler , fitur ini akan tersedia dalam C ++ 20 . Ini bisa digunakan dengan
<experimental/ranges/range>
tajuk. Makafor
pernyataannya akan terlihat seperti ini:Lihat DEMO 2
sumber
ranges::view
nama telah diubah namanya menjadiranges::views
. Jadi, gunakanranges::views::reverse
.Jika tidak menggunakan C ++ 14, maka saya menemukan solusi paling sederhana di bawah ini.
Demo .
Ini tidak berfungsi untuk wadah / tipe data (seperti array), yang tidak memiliki
begin/rbegin, end/rend
fungsi.sumber
Anda cukup menggunakan
BOOST_REVERSE_FOREACH
yang diulang mundur. Misalnya kodenyamenghasilkan output berikut:
sumber