Dalam +
ekspresi tersebut +[](){}
adalah +
operator unary . Ini didefinisikan sebagai berikut dalam [expr.unary.op] / 7:
Operand dari +
operator unary harus memiliki aritmatika, enumerasi tanpa batas, atau tipe pointer dan hasilnya adalah nilai argumen.
Lambda bukanlah tipe aritmatika dll., Tetapi dapat dikonversi:
[expr.prim.lambda] / 3
Tipe ekspresi lambda [...] adalah tipe kelas non-union unik dan tidak bernama - disebut tipe closure - yang propertinya dijelaskan di bawah ini.
[expr.prim.lambda] / 6
Jenis penutupan untuk lambda ekspresi tanpa lambda-capture memiliki public
non virtual
non explicit
const
fungsi konversi untuk pointer ke fungsi memiliki parameter dan return yang sama jenis sebagai operator fungsi panggilan jenis penutupan ini. Nilai yang dikembalikan oleh fungsi konversi ini harus menjadi alamat fungsi yang, ketika dipanggil, memiliki efek yang sama seperti memanggil operator panggilan fungsi tipe penutupan.
Oleh karena itu, unary +
memaksa konversi ke tipe penunjuk fungsi, yang untuk lambda ini void (*)()
. Oleh karena itu, tipe ekspresi +[](){}
adalah tipe penunjuk fungsi ini void (*)()
.
Kelebihan muatan kedua void foo(void (*f)())
menjadi Pencocokan Persis dalam peringkat untuk resolusi kelebihan muatan dan oleh karena itu dipilih dengan jelas (karena muatan berlebih pertama BUKAN Pencocokan Persis).
Lambda [](){}
dapat dikonversi ke std::function<void()>
melalui ctor template non-eksplisit std::function
, yang mengambil jenis apa pun yang memenuhi persyaratan Callable
dan CopyConstructible
.
Lambda juga dapat dikonversi void (*)()
melalui fungsi konversi tipe penutupan (lihat di atas).
Keduanya adalah urutan konversi yang ditentukan pengguna, dan memiliki peringkat yang sama. Itulah mengapa resolusi kelebihan beban gagal pada contoh pertama karena ambiguitas.
Menurut Cassio Neri, didukung oleh argumen Daniel Krügler, +
trik unary ini harus ditentukan perilaku, yaitu Anda dapat mengandalkannya (lihat diskusi di komentar).
Namun, saya akan merekomendasikan menggunakan cast eksplisit ke jenis penunjuk fungsi jika Anda ingin menghindari ambiguitas: Anda tidak perlu bertanya pada SO apa itu dan mengapa berfungsi;)
std::bind
kestd::function
objek yang bisa disebut mirip dengan nilai fungsi.