Misalkan saya memiliki generate_my_range
kelas yang memodelkan a range
(khususnya, adalah regular
). Lalu apakah kode berikut ini benar:
auto generate_my_range(int some_param) {
auto my_transform_op = [](const auto& x){ return do_sth(x); };
return my_custom_rng_gen(some_param) | ranges::views::transform(my_transform_op);
}
auto cells = generate_my_range(10) | ranges::to<std::vector>;
Apakah my_custom_rng_gen(some_param)
diambil dengan nilai oleh operator pipa (pertama), atau apakah saya memiliki referensi yang menggantung setelah saya meninggalkan generate_my_range
ruang lingkup?
Apakah akan sama dengan panggilan functionnal ranges::views::transform(my_custom_rng_gen(some_param),my_transform_op)
?
Apakah itu benar jika saya menggunakan referensi lvalue? misalnya:
auto generate_my_range(int some_param) {
auto my_transform_op = [](const auto& x){ return do_sth(x); };
auto tmp_ref = my_custom_rng_gen(some_param);
return tmp_ref | ranges::views::transform(my_transform_op);
}
Jika rentang diambil oleh nilai untuk operasi ini, lalu apa yang harus saya lakukan jika saya meneruskan referensi nilai rendah ke sebuah wadah? Haruskah saya menggunakan ranges::views::all(my_container)
pola?
Jawaban:
Di pustaka rentang ada dua jenis operasi:
Tampilannya ringan. Anda memberikan nilai dan mengharuskan wadah yang mendasarinya tetap valid dan tidak berubah.
Dari dokumentasi rentang-v3
dan:
Penghancuran wadah yang mendasari jelas membatalkan semua iterator untuk itu.
Dalam kode Anda, Anda secara spesifik menggunakan tampilan - Anda menggunakan
ranges::views::transform
. Pipa itu hanyalah gula sintaksis untuk membuatnya mudah ditulis seperti apa adanya. Anda harus melihat hal terakhir dalam pipa untuk melihat apa yang Anda hasilkan - dalam kasus Anda, ini adalah pemandangan.Jika tidak ada operator pipa, mungkin akan terlihat seperti ini:
jika ada beberapa transformasi yang terhubung dengan cara itu Anda bisa melihat bagaimana jeleknya itu akan terjadi.
Jadi, jika
my_custom_rng_gen
menghasilkan semacam wadah, yang Anda ubah dan kemudian kembali, wadah itu akan hancur dan Anda memiliki referensi yang menggantung dari pandangan Anda. Jikamy_custom_rng_gen
ada pandangan lain terhadap sebuah wadah yang hidup di luar lingkup ini, semuanya baik-baik saja.Namun, kompiler harus dapat mengenali bahwa Anda menerapkan tampilan pada wadah sementara dan memukul Anda dengan kesalahan kompilasi.
Jika Anda ingin fungsi Anda mengembalikan rentang sebagai wadah, Anda harus secara eksplisit "mematerialisasikan" hasilnya. Untuk itu, gunakan
ranges::to
operator dalam fungsi.Pembaruan: Untuk lebih tegas tentang komentar Anda "di mana dokumentasi mengatakan bahwa penyusunan rentang / perpipaan membutuhkan dan menyimpan tampilan?"
Pipa hanyalah gula sintaksis untuk menghubungkan berbagai hal dalam ekspresi yang mudah dibaca. Bergantung pada bagaimana digunakan, itu mungkin atau tidak dapat mengembalikan tampilan. Itu tergantung pada argumen sisi kanan. Dalam kasus Anda itu adalah:
Jadi ekspresi mengembalikan apa pun yang
views::transform
dikembalikan.Sekarang, dengan membaca dokumentasi transformasi:
Jadi ia mengembalikan suatu jangkauan, tetapi karena ia adalah operator yang malas, maka jangkauan yang dikembalikannya adalah sebuah tampilan, dengan semua semantiknya.
sumber
ranges::views::all(my_container)
? Dan bagaimana jika pandangan dilewatkan ke pipa? Apakah itu mengakui itu lewat wadah atau pemandangan? Apakah perlu? Bagaimana?my_custom_rng_gen
. Bagaimana tepatnya pipa dantransform
interaksi di bawah kap tidak penting. Seluruh ekspresi mengambil rentang sebagai argumen (wadah atau tampilan ke beberapa wadah) dan mengembalikan tampilan yang berbeda ke wadah itu. Nilai pengembalian tidak akan pernah memiliki wadah, karena itu adalah tampilan.Diambil dari dokumentasi rentang-v3 :
dan
Karena Anda mengatakan bahwa rentang sementara dapat dianggap sebagai wadah, fungsi Anda mengembalikan referensi yang menggantung.
Dengan kata lain, Anda perlu memastikan bahwa rentang yang mendasari hidup lebih lama dari tampilan, atau Anda dalam masalah.
sumber