ما هو المترجم الصحيح لسلوك الحمل الزائد/التخصص التالي؟
-
03-07-2019 - |
سؤال
النظر في الرمز التالي:
#include <stdio.h>
namespace Foo {
template <typename T>
void foo(T *, int) { puts("T"); }
template <typename T>
struct foo_fun {
static void fun() { foo((T *)0, 0); };
};
}
namespace Foo {
void foo(int *, int) { puts("int"); }
}
using namespace Foo;
int main() {
foo_fun<int> fun;
fun.fun();
}
ما هو الإخراج المتوقع؟ "T" أو int؟
أحد المترجمات (GCC 4.0.1 من Apple Xcode 3.1.2) إخراج "int" ، واثنين من المترجمين (GCC 4.1.2 و 4.1.3) الإخراج "T".
إذا قمت بنقل إعلان FOO (int *، int)/التعريف قبل إصدار FOO (t *، int) ، كل الإخراج "int". هل ترتيب التحميل الزائد/التخصص في هذه الحالة محددة بواسطة المعيار الحالي؟
المحلول
الثاني void foo(...
هو الحمل الزائد (وليس التخصص) غير مرئي في تعريف foo_fun::fun
لذلك لن يتم العثور عليه في سياق تعريف القالب. لان T*
هو نوع تابع ، حل foo
في التعبير foo((T*)0, 0)
سيتم تأخيره حتى وقت استئصال القالب وسيتم النظر في سياق الاستئصال. ومع ذلك ، 14.6.4.2 من المعيار يقول أنه إذا كان اسم الوظيفة هو معرف غير مؤهل ولكن ليس أ معرف القالب ثم بالنسبة للبحث عن غير ADL فقط ، يتم النظر في وظائف مرئية عند تعريف القالب. لا توجد حجج وظيفية من Foo
مساحة الاسم لذلك لا يحدث بحث تعتمد على الوسيطة ، وبالتالي نسخة القالب من foo
يسمى وليس الحمل الزائد غير المتجول.
شكرًا جزيلاً لـ Litb على التصحيحات لهذا الإجابة.
إذا جعلته تخصصًا على النحو التالي ، عند اختيار التخصصات في وقت استئصال القالب ، يمكن تسمية التخصص طالما أن التخصص ذي الصلة مرئي عند النقطة التي يتم فيها إنشاء قالب الوظيفة أولاً int
.
namespace Foo {
template<>
void foo<int>(int *, int) { puts("int"); }
}
الفصل 14 من المعيار الحالي ، لكنه ليس قابلاً للقراءة للغاية :)
تحرير: إذا اضطررت إلى اختيار الجزء الأكثر صلة من المعيار ، فمن المحتمل أن يكون 14.6 [temp.res] الفقرة 9. (اختصار قليلاً) إذا كان الاسم لا يعتمد على أ المعلمة قالب, ، يجب أن يكون إعلان هذا الاسم في نطاق عند ظهور الاسم في تعريف القالب ؛ يرتبط الاسم بالإعلان الموجود في تلك المرحلة وهذا الربط لا يتأثر بالإعلانات المرئية عند نقطة الاستئصال.
تحرير ، تحرير: ولكن عليك أيضًا أن تأخذ في الاعتبار 14.6.4.2 [temp.dep.candidate]. من الصعب للغاية وخطر محاولة الإشارة إلى المعيار بسبب كل الترابط ، هذه الإجابة هي مثال على ذلك.
نصائح أخرى
كقاعدة عامة ، من نسختين من برنامج التحويل البرمجي ، من المرجح أن يكون الأكثر قياسية.