ทำไมไม่ทำงาน
ฉันคาดหวังว่าคอมไพลเลอร์จะแก้ไขf()
ตามประเภทตัววนซ้ำ เห็นได้ชัดว่ามัน (gcc 4.1.2) ไม่ทำ
จะดีมากถ้าเป็นเช่นนั้น! อย่างไรก็ตามfor_each
เป็นเทมเพลตฟังก์ชันที่ประกาศเป็น:
template <class InputIterator, class UnaryFunction>
UnaryFunction for_each(InputIterator, InputIterator, UnaryFunction );
การหักเทมเพลตจำเป็นต้องเลือกประเภทสำหรับUnaryFunction
เมื่อมีการโทร แต่f
ไม่มีประเภทที่เฉพาะเจาะจง - เป็นฟังก์ชันที่มากเกินไปมีหลายf
ประเภทแต่ละประเภทมี ไม่มีวิธีปัจจุบันในfor_each
การช่วยกระบวนการหักเทมเพลตโดยระบุf
ว่าต้องการดังนั้นการหักเทมเพลตจึงล้มเหลว เพื่อให้การหักเทมเพลตประสบความสำเร็จคุณต้องทำงานเพิ่มเติมในไซต์การโทร
วิธีแก้ปัญหาทั่วไปในการแก้ไข
กระโดดเข้ามาที่นี่ไม่กี่ปีและ C ++ 14 ต่อมา แทนที่จะใช้ a static_cast
(ซึ่งจะช่วยให้การหักเทมเพลตสำเร็จโดยการ "แก้ไข" ที่f
เราต้องการใช้ แต่ต้องการให้คุณทำการแก้ปัญหาโอเวอร์โหลดด้วยตนเองเพื่อ "แก้ไข" ค่าที่ถูกต้อง) เราต้องการให้คอมไพเลอร์ทำงานให้เรา เราต้องการเรียกร้องให้f
บางส่วน ด้วยวิธีทั่วไปที่เป็นไปได้นั่นคือ:
[&](auto&&... args) -> decltype(auto) { return f(std::forward<decltype(args)>(args)...); }
มีจำนวนมากที่ต้องพิมพ์ แต่ปัญหาประเภทนี้เกิดขึ้นบ่อยครั้งจนน่ารำคาญดังนั้นเราจึงสามารถรวมสิ่งนั้นไว้ในมาโครได้ (ถอนหายใจ):
#define AS_LAMBDA(func) [&](auto&&... args) -> decltype(func(std::forward<decltype(args)>(args)...)) { return func(std::forward<decltype(args)>(args)...); }
จากนั้นใช้มัน:
void scan(const std::string& s) {
std::for_each(s.begin(), s.end(), AS_LAMBDA(f));
}
สิ่งนี้จะทำในสิ่งที่คุณต้องการให้คอมไพเลอร์ทำ - ทำการแก้ปัญหาโอเวอร์โหลดในชื่อf
ตัวเองและทำสิ่งที่ถูกต้อง สิ่งนี้จะใช้ได้ไม่ว่าf
จะเป็นฟังก์ชันฟรีหรือฟังก์ชันสมาชิกก็ตาม