Bagaimana cara membebani fungsi lambda lokal yang sederhana?
SSE masalah asli:
#include <iostream>
#include <map>
void read()
{
static std::string line;
std::getline(std::cin, line);
auto translate = [](int idx)
{
constexpr static int table[8]{ 7,6,5,4,3,2,1,0 };
return table[idx];
};
auto translate = [](char c)
{
std::map<char, int> table{ {'a', 0}, {'b', 1}, {'c', 2}, {'d', 3},
{'e', 4}, {'f', 5}, {'g', 6}, {'h', 7} };
return table[c];
};
int r = translate(static_cast<int>(line[0]));
int c = translate(static_cast<char>(line[1]));
std::cout << r << c << std::endl;
}
int main()
{
read();
return 0;
}
Pesan kesalahan
error: conflicting declaration 'auto translate'
note: previous declaration as 'read()::<lambda(int)> translate'
Tolong jangan keberatan tidak memeriksa input pengguna, ini adalah SSE.
c++
lambda
overloading
c++17
function-object
mengintip
sumber
sumber
translate
hanya variabel lokal yang tidak dapat menggunakan kembali nama yang sama.Jawaban:
Tidak, Anda tidak bisa membebani lambda!
Lambda adalah functor anonim (yaitu objek fungsi yang tidak disebutkan namanya), dan bukan fungsi sederhana. Karenanya, membebani benda-benda itu tidak mungkin dilakukan Apa yang pada dasarnya Anda coba lakukan hampir
Yang tidak mungkin, karena nama variabel yang sama tidak dapat digunakan kembali dalam C ++.
Namun, dalam c ++ 17 kita memiliki
if constexpr
satu yang dapat instantiate satu-satunya cabang yang benar pada waktu kompilasi.Berarti solusi yang mungkin adalah:
decltype
untukif constexpr
cek. (Kredit @NathanOliver )Menggunakan templat variabe Anda bisa melakukan sesuatu seperti. ( Lihat demo langsung online )
dan menyebutnya seperti
Menggunakan lambda generik (sejak c ++ 14 ), yang di atas adalah: ( Lihat demo online secara langsung )
dan panggil lambda seperti yang Anda lakukan sekarang:
sumber
else if
kebutuhan Andaelse if constexpr
. Kedua, mengapa menggunakan templat variabel? Anda bisa menjadikan lambda generik dan checl Anda akan menjadiif constexpr (std::is_same_v<decltype(idx), int>)
danelse if constexpr (std::is_same_v<decltype(idx), char>)
Lambdas pada dasarnya adalah gula sintaksis untuk functors yang ditentukan secara lokal. Sejauh yang saya tahu, mereka tidak pernah dimaksudkan untuk kelebihan beban dipanggil dengan parameter yang berbeda. Perhatikan bahwa setiap ekspresi lambda adalah tipe yang berbeda, sehingga meskipun kesalahan langsung disingkirkan, kode Anda tidak dapat berfungsi sebagaimana dimaksud.
Namun Anda dapat, mendefinisikan functor dengan kelebihan beban
operator()
. Ini akan persis seperti yang Anda dapatkan dari lambdas jika memungkinkan. Anda hanya tidak mendapatkan sintaks singkat.Sesuatu seperti:
sumber
Jadi aturan untuk overloading nama hanya berlaku untuk jenis pencarian nama fungsi tertentu (baik gratis maupun metode).
Lambdas bukan fungsi, mereka objek dengan operator fungsi-panggilan. Jadi kelebihan muatan tidak dapat terjadi antara dua lambda yang berbeda.
Sekarang, Anda bisa mendapatkan resolusi kelebihan untuk bekerja dengan objek fungsi, tetapi hanya dalam lingkup objek tunggal. Dan kemudian jika ada lebih dari satu
operator()
, resolusi kelebihan dapat memilih di antara mereka.Namun, lambda tidak memiliki cara yang jelas untuk memiliki lebih dari satu
operator()
. Kita dapat menulis kelas utilitas sederhana (dalam c ++ 17 ) untuk membantu kami:dan panduan deduksi:
dengan dua ini, kita bisa membebani dua lambda:
dan dilakukan.
Menulis
overloaded
dimungkinkan di c ++ 14 dan c ++ 11 tetapi membutuhkan lebih banyak pekerjaan dan kurang elegan. Setelah Anda mengetahui masalahnya, menemukan solusi yang cocok dengan apa yang didukung kompiler khusus Anda di jalan fitur C ++ seharusnya tidak sulit.sumber
variadic generic lamda
+if constexpr
untuk memisahkan panggilan?