c++ - متى تكون الكلمة المفتاحية "typename" ضرورية؟




templates syntax (2)

إجابة قصيرة: عندما تشير إلى اسم متداخل هو اسم تابع ، أي متداخلة داخل مثيل قالب به معلمة غير معروفة.

إجابة طويلة: هناك ثلاثة مستويات من الكيانات في C ++: القيم ، والأنواع ، والقوالب. كل هؤلاء يمكن أن يكون لديهم أسماء ، والاسم وحده لا يخبركم بأي فئة من الكيانات. بدلاً من ذلك ، يجب الاستدلال على المعلومات المتعلقة بطبيعة كيان الاسم من السياق.

كلما كان هذا الاستنتاج مستحيلاً ، يجب عليك تحديده:

template <typename> struct Magic; // defined somewhere else

template <typename T> struct A
{
  static const int value = Magic<T>::gnarl; // assumed "value"

  typedef typename Magic<T>::brugh my_type; // decreed "type"
  //      ^^^^^^^^

  void foo() {
    Magic<T>::template kwpq<T>(1, 'a', .5); // decreed "template"
    //        ^^^^^^^^
  }
};

هنا يجب أن يتم تفسير أسماء Magic<T>::gnarl و Magic<T>::brugh و Magic<T>::kwpq kwpq ، لأنه من المستحيل معرفة ما يلي: بما أن Magic قالب ، فإن طبيعة النوع يعتمد Magic<T> على T - قد تكون هناك تخصصات مختلفة تمامًا عن النموذج الأساسي ، على سبيل المثال.

ما الذي يجعل Magic<T>::gnarl اسمًا تابعًا هو حقيقة أننا داخل تعريف القالب ، حيث T غير معروف. لو استخدمنا Magic<int> ، فسيكون هذا مختلفًا ، لأن المجمع يعرف (الذي تعد به!) التعريف الكامل لـ Magic<int> .

(إذا كنت ترغب في اختبار هذا بنفسك ، فإليك مثالاً لتعريف Magic يمكنك استخدامه. عفو عن استخدام constexpr في التخصص للإيجاز ؛ إذا كان لديك مترجم قديم ، constexpr تتردد في تغيير إعلان ثابت العضو الثابت إلى القديم نمط قبل C + + 11.)

template <typename T> struct Magic
{
  static const T                    gnarl;
  typedef T &                       brugh;
  template <typename S> static void kwpq(int, char, double) { T x; }
};
template <> struct Magic<signed char>
{
  // note that `gnarl` is absent
  static constexpr long double brugh = 0.25;  // `brugh` is now a value
  template <typename S> static int kwpq(int a, int b) { return a + b; }
};

الاستعمال:

int main()
{
  A<int> a;
  a.foo();

  return Magic<signed char>::kwpq<float>(2, 3);  // no disambiguation here!
}

ممكن تكرار:
رسميا ، ما هو اسم الملف؟
أين ولماذا يجب علي وضع القالب والكلمة الرئيسية؟

النظر في الكود أدناه:

template<class K>
class C {
    struct P {};
    vector<P> vec;
    void f();
};

template<class K> void C<K>::f() {
    typename vector<P>::iterator p = vec.begin();
}

لماذا الكلمة الأساسية "typename" ضرورية في هذا المثال؟ هل هناك أي حالات أخرى يجب فيها تحديد "typename"؟


الكلمة الأساسية typename ، مطلوبة لأن iterator هو نوع تابع على P لا يستطيع المترجم أن يخمّن إذا كان iterator يشير إلى قيمة أو نوع ، لذا فإنه يفترض قيمة ما لم تصيح typename . هناك حاجة كلما كان هناك نوع يعتمد على وسيطة قالب ، في سياق إما أن تكون الأنواع أو القيم صالحة. على سبيل المثال ، لا تحتاج إلى فصول أساسية مثل typename لأن الفئة الأساسية يجب أن تكون من النوع.

في نفس الموضوع ، هناك الكلمة الأساسية template المستخدمة للسماح للمتحقق معرفة أن بعض الاسم التابع هو دالة قالب بدلاً من قيمة.





typename