ما هو المترجم الصحيح لسلوك الحمل الزائد/التخصص التالي؟

StackOverflow https://stackoverflow.com/questions/403929

سؤال

النظر في الرمز التالي:

#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]. من الصعب للغاية وخطر محاولة الإشارة إلى المعيار بسبب كل الترابط ، هذه الإجابة هي مثال على ذلك.

نصائح أخرى

كقاعدة عامة ، من نسختين من برنامج التحويل البرمجي ، من المرجح أن يكون الأكثر قياسية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top