Apakah mungkin untuk menangkap dengan referensi const dalam ekspresi lambda?
Saya ingin tugas yang ditandai di bawah gagal, misalnya:
#include <cstdlib>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
string strings[] =
{
"hello",
"world"
};
static const size_t num_strings = sizeof(strings)/sizeof(strings[0]);
string best_string = "foo";
for_each( &strings[0], &strings[num_strings], [&best_string](const string& s)
{
best_string = s; // this should fail
}
);
return 0;
}
Pembaruan: Karena ini adalah pertanyaan lama, mungkin baik untuk memperbaruinya jika ada fasilitas di C ++ 14 untuk membantu dengan ini. Apakah ekstensi dalam C ++ 14 memungkinkan kita untuk menangkap objek non-const dengan referensi const? ( Agustus 2015 )
[&, &best_string](string const s) { ...}
?Jawaban:
const
tidak ada dalam tata bahasa untuk menangkap pada n3092:Teks hanya menyebutkan capture-by-copy dan capture-by-reference dan tidak menyebutkan jenis ketegasan.
Rasanya seperti kekeliruan bagi saya, tetapi saya belum mengikuti proses standardisasi dengan sangat cermat.
sumber
const
. Atau lebih tepatnya, jika variabel capture adalahconst
, kompiler akan memberlakukan perilaku yang benar pada programmer. Alangkah baiknya jika sintaks didukung[&mutableVar, const &constVar]
.a
sebagaiconst
, nyatakan diconst auto &b = a;
depan lambda dan tangkapb
[&foo = this->foo]
di dalam suatuconst
fungsi memberi saya kesalahan yang menyatakan bahwa tangkapan itu sendiri membuang kualifikasi. Ini bisa jadi bug di GCC 5.1, saya kira.Di c ++ 14menggunakan
static_cast
/const_cast
:DEMO
Di c ++ 17menggunakan
std::as_const
:DEMO 2
sumber
const_cast
dapat tanpa syarat mengubah objek volatil ke objek const (ketika diminta untuk melakukan castconst
), dengan demikian, untuk menambahkan kendala yang saya sukaistatic_cast
static_cast
untuk referensi const dapat secara diam-diam membuat sementara jika Anda tidak mendapatkan tipe yang tepat&basic_string = std::as_const(best_string)
harus menyelesaikan semua masalahconst& best_string
.Saya pikir bagian penangkapan seharusnya tidak menentukan
const
, karena artinya penangkapan, itu hanya perlu cara untuk mengakses variabel lingkup luar.Specifier lebih baik ditentukan dalam lingkup luar.
fungsi lambda adalah const (tidak dapat mengubah nilai dalam cakupannya), jadi ketika Anda menangkap variabel dengan nilai, variabel tidak dapat diubah, tetapi referensi tidak dalam cakupan lambda.
sumber
better_string
dalam lingkup yang berisi, maka solusi ini tidak akan berfungsi. Kasus penggunaan untuk menangkap sebagai const-ref adalah ketika variabel harus bisa berubah dalam lingkup yang berisi tetapi tidak di dalam lambda.const string &c_better_string = better_string;
dan dengan senang hati mengirimkannya ke lambda:[&c_better_string]
Saya kira jika Anda tidak menggunakan variabel sebagai parameter dari functor, maka Anda harus menggunakan level akses dari fungsi saat ini. Jika Anda merasa tidak seharusnya, maka pisahkan lambda Anda dari fungsi ini, itu bukan bagian darinya.
Bagaimanapun, Anda dapat dengan mudah mencapai hal yang sama yang Anda inginkan dengan menggunakan referensi const lain:
Tapi itu sama dengan mengasumsikan bahwa lambda Anda harus diisolasi dari fungsi saat ini, menjadikannya non-lambda.
sumber
best_string
hanya. Selain itu, GCC 4.5 "berhasil menolak" kode yang dimaksud.Saya pikir Anda memiliki tiga opsi berbeda:
menggunakan salinan
Bagian yang menarik tentang lambda dengan salinan salinan adalah bahwa itu sebenarnya hanya dibaca dan karena itu lakukan persis apa yang Anda inginkan.
menggunakan std :: bind
std::bind
mengurangi arity dari suatu fungsi. Namun perlu dicatat bahwa ini mungkin / akan menyebabkan panggilan fungsi tidak langsung melalui pointer fungsi.sumber
Ada cara yang lebih pendek.
Perhatikan bahwa tidak ada tanda dan sebelum "best_string".
Ini akan menjadi tipe "const std :: reference_wrapper << T >>".
http://coliru.stacked-crooked.com/a/0e54d6f9441e6867
sumber
Gunakan dentang atau tunggu sampai bug gcc ini diperbaiki: bug 70385: Lambda capture dengan referensi referensi const gagal [ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70385 ]
sumber
Menggunakan const hanya akan memiliki algoritma ampersand mengatur string ke nilai aslinya, Dengan kata lain, lambda tidak akan benar-benar mendefinisikan dirinya sebagai parameter fungsi, meskipun lingkup sekitarnya akan memiliki variabel tambahan ... Tanpa mendefinisikannya meskipun, itu tidak akan mendefinisikan string sebagai khas [&, & best_string] (string const s) Oleh karena itu , kemungkinan besar lebih baik jika kita membiarkannya, mencoba menangkap referensi.
sumber