في بعض الحالات ، يتعذر على برنامج التحويل البرمجي لـ C ++ تحديد وظيفة التحميل الزائد المناسبة ، على سبيل المثال ، في موقف يتضح من وجهة نظر بشرية - يحدث خطأ في الترجمة:
void f(int i){} void f(string s){} vector<int> int_c = { 1, 2, 3, 4, 5 }; vector<string> string_c = { "Sic" ,"transit" ,"gloria" ,"mundi" }; for_each(begin(int_c), end(int_c), f);//error C2672: "for_each":      
المشكلة هي نقص المعلمات f في السطر الأخير ، والتي يمكن للمترجم حل الزائد. حقيقة أن التكرار من نوع محدد للغاية يتم تمرير معلمات for_each لا يهم للمترجم.
يمكنك تقديم عدة طرق "أمامية" لحل المشكلة:
1) استخدام static_cast <> () لفرض المصبوب على مؤشر دالة من النوع المطلوب.
نحن يلقي بالمؤشر لإلغاء f (int i):
 std::for_each(begin(int_c), end(int_c), static_cast<void (*)(int)>(&f)); 
نحن يلقي بالمؤشر لإلغاء f (السلسلة i):
 std::for_each(begin(string_c), end(string_c), static_cast<void (*)(string)>(&f)); 
2) تعريف المؤشرات إلى الوظائف واستخدامها.
نستخدم الفراغ f (int i):
  void (*fp_int)(int) = &f; for_each(begin(int_c), end(int_c), fp_int); 
نستخدم الفراغ f (السلسلة i):
 void (*fp_string)(string) = &f; for_each(begin(string_c), end(string_c), fp_string); 
3) إنشاء تخصصات واضحة لوظيفة القالب for_each:
نستخدم الفراغ f (int i):
 std::for_each<vector<int>::const_iterator, void(*)(int) >(int_c.begin(), int_c.end(), f); 
نستخدم الفراغ f (السلسلة i):
 std::for_each<vector<string>::const_iterator, void(*)(string) >(string_c.begin(), string_c.end(), f); 
أو أكثر إحكاما:
 std::for_each<decltype(int_c.begin()), void(*)(int) >(int_c.begin(), int_c.end(), f); std::for_each<decltype(string_c.begin()), void(*)(string) >(string_c.begin(), string_c.end(), f); 
الأساليب المقترحة أعلاه ليست عالمية وتؤدي إلى الحاجة إلى تطوير رمز إضافي على جانب الاتصال. أفضل فكرة هي إنشاء قشرة رقيقة فوق الوظيفة f والتي تأخذ معلمات الدالة f وتمريرها إليها دون تغييرات.
من الضروري أيضًا النظر في الاحتمالات:
- وجود عدد غير محدد من معلمات الدالة f ،
 - وجود القيمة المرجعة للدالة ،
 - تمرير المعلمات حسب المرجع ،
 - وجود تصفيات المعلمات السيرة الذاتية ،
 - استثناءات في الوظيفة f.
 
خطوة بخطوة سنقوم بتحليل بناء مثل هذه قذيفة. وظيفة لامدا هي أساس جيد. بدعم من C ++ 11 القياسي من قبل المترجم ، يمكن تنفيذ هذا على النحو التالي:
 for_each(begin(int_c), end(int_c), [](int a) { return f(a); }); for_each(begin(string_c), end(string_c), [](string a) { return f(a); }); 
أو باستخدام Dectype ():
 for_each(begin(int_c), end(int_c), [](decltype(*int_c.begin()) a) { return f(a); }); for_each(begin(string_c), end(string_c), [](decltype(*string_c.begin()) a) { return f(a); }); 
بدعم من المعيار C ++ 14 من قبل المترجم ، لدينا الحل التالي للحصول على لامدا متعدد الأشكال:
 auto l = [](auto a) { return f(a); }; for_each(begin(int_c), end(int_c), l); for_each(begin(string_c), end(string_c), l); 
لذلك ، نقوم بتمرير المعلمة إلى الدالة f كمعلمة إلى lambda ، ثم ندعو f مع هذه المعلمة. ولكن هناك مشكلة: لا نعرف مقدمًا - هل معلمات الدالة f القيم أو المراجع؟ لذلك ، يجب عليك استخدام العتاد المثالي.
 auto l = [](auto&& a) { return f(std::forward<decltype(a)>(a)); }; for_each(begin(int_c), end(int_c), l); for_each(begin(string_c), end(string_c), l); 
حول موضوع انتقال مثالي (إعادة توجيه مثالية) يمكن العثور عليها في مايرز [1]. يمكن الاطلاع على نسخة أكثر قابلية للفهم (بالنسبة لي ، على أي حال) من عرض نفس المادة في المادة [2] ، وترجمتها على حبري [3].
بالنسبة لعدد غير محدد من معلمات الدوال ، فإننا نشير إلى معلمات lambda كمتغير قادر وندعو std :: forward لكل معلمة تنتقل إلى f.
  auto l = [](auto&&... a) { return f(std::forward<decltype(a)>(a)...); }; 
نضيف noexcept لمحدِّد وقت برنامج التحويل البرمجي [4] ومشغل noexcept [5] للإشارة إلى المترجم ما إذا كانت الدالة f ستلقي استثناءات [6].
  auto l = [](auto&&... a) \ noexcept(noexcept(f(std::forward<decltype(a)>(a)...)))\ { return f(std::forward<decltype(a)>(a)...); }; 
إضافة إخراج نوع القيمة المرجعة لامدا شيدت.
  auto l = [](auto&&... a) \ noexcept(noexcept(f(std::forward<decltype(a)>(a)...)))\ -> decltype(f(std::forward<decltype(a)>(a)...))\ { return f(std::forward<decltype(a)>(a)...); }; 
إذا كان تكرار الرمز الثلاثي مزعجًا ولا نتردد في استخدام وحدات الماكرو - فيمكنك تقليل الحجم في جانب الاتصال.
 #define LIFT(foo) \ [](auto&&... x) \ noexcept(noexcept(foo(std::forward<decltype(x)>(x)...))) \ -> decltype(foo(std::forward<decltype(x)>(x)...)) \ { return foo(std::forward<decltype(x)>(x)...); } 
كنتيجة لذلك ، لدينا غلاف يساعد المترجم على حل دالة overloaded.
 for_each(begin(int_c), end(int_c), LIFT(f)); for_each(begin(string_c), end(string_c), LIFT(f)); 
[1] س. مايرز "C ++ الحديثة الفعالة" البند 24: تمييز المراجع العالمية من مراجع rvalue.
[2] 
eli.thegreenplace.net/2014/perfect-forwarding-and-universal-references-in-c[3] 
habr.com/en/post/242639[4] 
en.cppreference.com/w/cpp/language/noexcept_spec[5] 
en.cppreference.com/w/cpp/language/noexcept[6] 
habr.com/en/post/164221[7] 
www.fluentcpp.com 2017/08/01 / Overloaded-functions-stl[8] 
www.youtube.com/watch؟v=I3T4lePH-yA