c++ - استخدام الكلمة الرئيسية typename مع معلمات وظيفة القالب




templates (2)

في C ++ ، هناك حاجة إلى الكلمة المفتاحية typename بحيث يمكن typename بين الأنواع المتداخلة والقيم المتداخلة في القوالب. ومع ذلك ، هناك حالات معينة لا يكون فيها الغموض ممكنًا ، مثل عندما ترث طبقة مشتقة من نوع فئة متداخلة.

template <class T>
class Derived : public T::type
{ };

هنا الكلمة الرئيسية typename غير مطلوبة ، وفي الواقع غير مسموح بها. هذا منطقي ، لأن السياق يزيل الغموض. هنا ، يجب أن تشير T::type إلى نوع ، حيث أنه من الواضح أنك لا تستطيع أن ترث من قيمة ما.

أعتقد أن نفس الشيء سيصدق على معلمات نموذج الوظيفة.

template <class T>
void foo(const T::type& v)
{

}

في هذه الحالة ، يوضح السياق أن T::type يجب أن يشير إلى نوع ، لأن معلمة الدالة لا يمكن أن تكون قيمة. ومع ذلك ، لا يقبل المترجم هذا. انها تريد const typename T::type& . هذا يبدو غير متناسق. لماذا تسمح اللغة بالافتراض الضمني لنوع متداخل في سياق الميراث ، ولكن ليس في سياق بارامترات الوظائف؟ في كلتا الحالتين لا يمكن أن يكون هناك غموض ، فلماذا الحاجة إلى اسم typename في واحد ولكن ليس الآخر؟


أولاً ، لا أعتقد أن هناك أي نية لعمل تمييز حاد ودقيق بين المواقف التي يُسمح فيها فقط بأسماء المواقع (مثل اسم الطبقة الأساسية) والمواقف التي يُسمح فيها بالكيانات غير النوعية (مثل التعبيرات). أود أن أقول إن سياق اسم الفئة الأساسية قد اختير لسبب آخر.

ثانياً ، ليس صحيحاً تماماً القول أنه في إعلانات المعلمات الوظيفية ، كل كيان هو بالضرورة اسم مطبعي. يمكنك الإعلان عن المعلمة على النحو التالي

template <class T>
void foo(const T::type& v[T::value]);

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


إذا قمت بتغيير الإعلان الخاص بك قليلاً ، فإنك تحصل على قصة مختلفة بالكامل

template <class T>
void foo(T::type& v);

هذا ليس واضحًا بعد الآن. يمكن أن تعلن عن متغير من نوع void الذي تتم تهيئته بواسطة تعبير AND bit. الإعلان الكامل سيكون templated. وبالطبع ، فإن هذا المنطق هو كل شيء هراء ، إلا أنه من الناحية البناءية على ما يرام.

إن مظهر const يجعله لا لبس فيه ، لكنه كثير الاعتماد على السياق لجعل هذا العمل في المترجم. يجب أن نتذكر أنه يقرأ const أو أي شيء آخر مماثل ، وعندما يوزع T::type بعد أن تحتاج إلى تذكر أن تأخذ هذا الاسم كنوع. ومن شأنه أيضا أن ينفخ المعيار المعقد بالفعل أكثر من الاعتقاد.

دعونا مرة أخرى تغيير إعلان الدالة الخاصة بك

template <class T>
void foo(const T::type);

ولا حتى مظهر const هناك يوفر تحليلًا لا لبس فيه. هل يجب أن تكون عبارة عن تعريف دالة مع معلمة غير مسمّاة ، أم يجب أن تكون عبارة عن تعريف دالة مع اسم معلمة غير صالح يفوت بنوعه؟ يتم تحليل اسم المعلمة بواسطة declarator-id ، والذي يمكن أن يكون أيضًا اسمًا مؤهلاً. إذن ، هنا ، ستنتقل const إلى النوع المحدد ، بينما سيتم تحليل T::type بواسطة المحول البرمجي كاسم المعلمة ، في غياب اسم typename . هذا هراء تمامًا أيضًا ، ولكنه صحيح بشكل صحيح .

في حالة البحث عن أسماء اسم فئة أساسية تشير إلى أنه يتم تجاهل أسماء غير النوع. حتى تحصل على حذف اسم typename المجاني: الاسم الذي ينتج عنه اسم البحث إلى وحدات مستوى أعلى من المحول البرمجي إما يشير إلى نوع ، أو سيعطي البحث عن الاسم خطأً.

لقد كتبت إدخال أسئلة وأجوبة حول مكان وضع "القالب" و "typename" على أسماء تابعة .





typename