c++ - قرار الزائد من وظائف القالب




templates overload-resolution (2)

لا يأخذ خصم وسيطة القالب نوع الإرجاع في الاعتبار ،

نعم. يتم تنفيذ خصم وسيطة القالب على أساس وسيطات الدالة.

فلماذا max<int> غامض وليس max<double> ؟

ونظرا ::max<int>(7, 4.) ، بالنسبة إلى التحميل الزائد الأول ، يتم تحديد المعلمة الأولى للقالب T1 على أنها int ، ويتم استنتاج T2 على أنه double من وسيطة الوظيفة الثانية 4. ، عندئذٍ سيكون double max(int, double) . بالنسبة إلى التحميل الزائد الثاني ، يتم تحديد المعلمة الأولى للقالب RT على أنها int ، ويتم استنتاج T1 كـ int من 7 ، ويتم استنتاج T2 على أنه double من 4. ، ثم تكون int max(int, double) . لا تعتبر دقة التحميل الزائد نوع الإرجاع أيضًا ، الحمولة الزائدة متطابقتان تمامًا ومن ثم غامضة.

بالنظر إلى ::max<double>(7, 4.) ، بالنسبة إلى التحميل الزائد الأول ، يتم تحديد المعلمة الأولى للقالب T1 على أنها double ، ويتم استنتاج T2 على أنه double من 4. ، بحيث يكون إنشاء مثيل double max(double, double) . بالنسبة إلى التحميل الزائد الثاني ، يتم تعيين المعلمة الأولى للقالب RT على أنها double ، ويتم استنتاج T1 كـ int من 7 ، ويتم استنتاج T2 على أنه double من 4. ، ثم يكون إنشاء مثيل double max(int, double) . ثم يفوز الحمل الزائد الثاني في دقة التحميل الزائد لأنه تطابق تام ، الأول يتطلب التحويل الضمني من int إلى double للوسيطة الأولى 7 .

النظر في هذا الرمز:

#include <iostream>

//Number1
template<typename T1, typename T2>
auto max (T1 a, T2 b)
{
    std::cout << "auto max(T1 a, T2 b)" <<std::endl;
    return  b < a ? a : b;
}

//Number2
template<typename RT, typename T1, typename T2>
RT max (T1 a, T2 b)
{
    std::cout << "RT max(T1 a, T2 b)" << std::endl;
    return  b < a ? a : b;
}


int main()
{
    auto a = ::max(4, 7.2);         //Select Number1

    auto b = ::max<double>(4, 7.4); //Select Number2

    auto c = ::max<int>(7, 4.);     //Compile-time error overload ambiguous

    auto c = ::max<double>(7, 4.); //Select Number2

}

auto c = ::max<int>(7, 4.); : فشل ترجمة هذا الخط بسبب غموض التحميل الزائد بالرسالة التالية:

maxdefault4.cpp:9:27: error: call of overloaded 'max(int, double)' is ambiguous
  auto c = ::max<int>(7, 4.);
                           ^
maxdefault4.cpp:9:27: note: candidates are:
In file included from maxdefault4.cpp:1:0:
maxdefault4.hpp:4:6: note: auto max(T1, T2) [with T1 = int; T2 = double]
 auto max (T1 a, T2 b)
      ^
maxdefault4.hpp:11:4: note: RT max(T1, T2) [with RT = int; T1 = int; T2 = double]
 RT max (T1 a, T2 b)
    ^

بينما àuto c = ::max<double>(7, 4.) التعليمة البرمجية التالية: àuto c = ::max<double>(7, 4.) ، لماذا لا نحصل على نفس رسالة الخطأ التي تقول أن المكالمة غامضة بالنسبة لـ max<double> بالطريقة نفسها max<int> فشل ؟

لماذا double لا توجد مشكلة؟

لقد قرأت في كتاب "قوالب C ++ ، دليل الإكمال" أن خصم وسيطة القالب لا يأخذ نوع الإرجاع في الاعتبار ، فلماذا يكون max<int> غامضًا وليس max<double> ؟

هل لا يُؤخذ نوع الإرجاع لوظيفة القالب في الاعتبار في استنتاج الوسيطة؟


لكل من استدعاءات وظيفتك ، يحتوي المترجم على وظيفتين للاختيار من بينها ويختار الأفضل. يتم استخلاص معلمات قالب غير معروفة من الوسيطات بصرف النظر عن RT والتي يجب تحديدها بشكل صريح ولا يمكن استنتاجها.

auto a = ::max(4, 7.2);

نظرًا لعدم تحديد RT ولا يمكن استنتاجه ، فإن التحميل الزائد الثاني لا يمكن استخدامه ، وبالتالي يتم تجاهله. يتم اختيار الأول ويتم استنتاج الأنواع كـ int و double .

auto b = ::max<double>(4, 7.4);

تم تحديد RT الآن بحيث يمكن للمترجم اختيار إما استخدام max<double,int,double> أو max<double, double> ، تتطابق أنواع الوسيطة الخاصة بإصدار معلمة القالب 3 مع وسيطات الدالة تمامًا بينما يتطلب إصدار المعلمة 2 القالب بالضبط يلقي من int إلى double بحيث يتم اختيار الزائد 3 المعلمة.

auto c = ::max<int>(7, 4.);

تم تحديد RT الآن بحيث يمكن للمترجم اختيار إما استخدام max<int,int,double> أو max<int, double> ، وأنواع الوسيطة كلا الوظيفتين أصبحت الآن متماثلة بحيث لا يمكن للمترجم الاختيار بينها.





overload-resolution