+
ในการแสดงออก+[](){}
เป็นเอกภาค+
ผู้ประกอบการ มีการกำหนดดังต่อไปนี้ใน [expr.unary.op] / 7:
ตัวถูกดำเนินการของตัวดำเนิน+
การยูนารีต้องมีเลขคณิตการแจงนับที่ไม่ได้กำหนดขอบเขตหรือชนิดของตัวชี้และผลลัพธ์คือค่าของอาร์กิวเมนต์
แลมด้าไม่ใช่ประเภทเลขคณิตเป็นต้น แต่สามารถแปลงได้:
[expr.prim.lambda] / 3
ประเภทของlambda-expression [... ] เป็นคลาสที่ไม่ซ้ำกันไม่มีชื่อเรียกว่าประเภทการปิดซึ่งมีการอธิบายคุณสมบัติไว้ด้านล่าง
[expr.prim.lambda] / 6
ประเภทปิดสำหรับแลมบ์ดาแสดงออกที่ไม่มีแลมบ์ดาจับมีpublic
ไม่ใช่virtual
ไม่ใช่explicit
const
ฟังก์ชั่นการแปลงตัวชี้ไปยังฟังก์ชั่นที่มีพารามิเตอร์และผลตอบแทนเดียวกันเป็นผู้ประกอบการประเภทฟังก์ชั่นการโทรประเภทปิดของ ค่าที่ส่งคืนโดยฟังก์ชันการแปลงนี้จะเป็นที่อยู่ของฟังก์ชันที่เมื่อเรียกใช้จะมีผลเช่นเดียวกับการเรียกใช้ตัวดำเนินการเรียกฟังก์ชันของประเภทการปิด
ดังนั้นยูนารี+
บังคับให้แปลงเป็นชนิดตัวชี้ฟังก์ชันซึ่งเป็นของแลมบ์ดาvoid (*)()
นี้ ดังนั้นประเภทของนิพจน์+[](){}
จึงเป็นประเภทตัวชี้ฟังก์ชันvoid (*)()
นี้
การโอเวอร์โหลดครั้งที่สองvoid foo(void (*f)())
จะกลายเป็นการจับคู่แบบตรงทั้งหมดในการจัดอันดับสำหรับการแก้ปัญหาโอเวอร์โหลดดังนั้นจึงถูกเลือกอย่างไม่น่าสงสัย (เนื่องจากการโอเวอร์โหลดครั้งแรกไม่ใช่การจับคู่แบบตรงทั้งหมด)
แลมบ์ดา[](){}
สามารถแปลงเป็นstd::function<void()>
ผ่าน ctor เทมเพลตที่ไม่ชัดเจนstd::function
ซึ่งใช้ประเภทใดก็ได้ที่ตรงตามข้อกำหนดCallable
และCopyConstructible
ข้อกำหนด
แลมบ์ดายังสามารถแปลงvoid (*)()
เป็นฟังก์ชั่นการแปลงของประเภทการปิด (ดูด้านบน)
ทั้งสองเป็นลำดับ Conversion ที่ผู้ใช้กำหนดเองและมีอันดับเดียวกัน นั่นเป็นสาเหตุที่ความละเอียดเกินพิกัดล้มเหลวในตัวอย่างแรกเนื่องจากความไม่ชัดเจน
ตามที่ Cassio Neri ได้รับการสนับสนุนจากการโต้แย้งโดย Daniel Krügler +
เคล็ดลับที่เป็นเอกภาพนี้ควรระบุพฤติกรรมกล่าวคือคุณสามารถพึ่งพาได้ (ดูการอภิปรายในความคิดเห็น)
อย่างไรก็ตามฉันขอแนะนำให้ใช้การแคสต์อย่างชัดเจนกับประเภทตัวชี้ฟังก์ชันหากคุณต้องการหลีกเลี่ยงความคลุมเครือ: คุณไม่จำเป็นต้องถามว่า SO คืออะไรและทำไมถึงใช้งานได้;)
std::bind
ไปยังstd::function
วัตถุที่สามารถเรียกคล้ายกับ lvalue ฟังก์ชั่น