نشر "typedef" من الفئة المستندة إلى الفئة المشتقة لـ "القالب"
-
10-07-2019 - |
سؤال
أحاول تحديد الفئة الأساسية التي تحتوي على typedef فقط.
template<typename T>
class A
{
public:
typedef std::vector<T> Vec_t;
};
template<typename T>
class B : public A<T>
{
private:
Vec_t v; // fails - Vec_t is not recognized
};
لماذا أتلقى في B خطأ مفاده أنه لم يتم التعرف على Vec_t وأحتاج إلى كتابته بشكل صريح؟
typename A<T>::Vec_t v;
المحلول
أعتقد أن هذا السؤال مكرر، لكن لا يمكنني العثور عليه الآن.يقول معيار C++ أنه يجب عليك تأهيل الاسم بالكامل وفقًا لـ 14.6.2/3:
في تعريف قالب الفصل أو عضو قالب الفصل، إذا كانت الفئة الأساسية لقالب الفصل تعتمد على معلمة القالب، فإن لم يتم فحص نطاق الفئة الأساسية أثناء البحث عن اسم غير مؤهل إما عند نقطة تعريف قالب الفصل أو العضو أو أثناء إنشاء مثيل لقالب الفصل أو العضو.
محدث: لقد وجدت نسخة مكررة أخيرًا: ها هو.
نصائح أخرى
وهناك ما يسمى تعتمد و<م> nondependent م> الأسماء في حالة القوالب.
إذا يعتمد الاسم على معلمة قالب T لها <م> يعتمد م> اسم وغيرهم الذين لا تعتمد على المعلمة T و<م> مستقلة م> أسماء.
<اقتباس فقرة>وهنا القاعدة: المترجم لا ابحث في الفئات الأساسية التي تعتمد (مثل A) عند البحث عن nondependent أسماء (مثل Vec_t). كنتيجة ل، المترجم لا يعرفون أنهم حتى موجودة ناهيك هي أنواع.
اقتباس فقرة> ومترجم لا يمكن أن نفترض أن Vec_t
هو نوع حتى يعرف T
لأن هناك تخصص محتملا للA<T>
حيث A<T>:: Vec_t
هو عضو البيانات
وبالتالي فإن الحل هو استخدام typename
typename A<T>::Vec_t v; ← good
وأوصي تذهب من خلال هذا https://isocpp.org/ ويكي / أسئلة وأجوبة / القوالب #-أنواع-اسم nondependent-بحث .
قديم (كسر) رابط: HTTP: // شبكة الاتصالات العالمية. parashift.com/c++-faq-lite/templates.html#faq-35.18
ولأن المترجم ليس على يقين من أن أسماء Vec_t
نوع. على سبيل المثال، قد يكون A<T>
متخصصة لT=int
إلى <م> لا م> التي لها نفس typedef
وجه الخصوص.
للاكتمال، إليك كيفية تخفيف هذا الإزعاج قليلاً، إما:
- إعادة وضع هذه الأنواع في الفصول المشتقة ، أو أفضل - كما هو الحال مع الأساليب -
- ما عليك سوى استيراد هذه الأسماء في نطاق الفئة المشتقة باستخدام ملف
using declaration
:
template<typename T>
class A
{
public:
typedef std::vector<T> Vec_t;
};
template<typename T>
class B : public A<T>
{
public:
using typename A<T>::Vec_t;
// .........
private:
Vec_t v;
};
يمكن أن يكون مفيدًا إذا كان لديك أكثر من ذكر للموروثة typedef
في الطبقة المشتقة.كما لا تحتاج إلى إضافة typename
في كل مرة مع هذا.
وتحتاج إلى تأهيل صراحة استخدام Vec_t
لأن المترجم لا يعرف من أين يأتي Vec_t
من.
لا يمكن تحمل أي شيء عن هيكل A، لأن الطبقة قالب A قد تكون متخصصة. ويمكن أن تشمل التخصص في Vec_t
وهي ليست typedef و، أو أنه قد لا تشمل حتى Vec_t
عضوا على الإطلاق.
وVec_t ليس اسما معتمدا، والمترجم يحتاج إلى معرفة ما هو عليه دون instantiating أية قوالب (الفئة الأساسية في هذه الحالة). انها حقا لا يختلف عن:
template <class T>
class X
{
std::string s;
}
وهنا أيضا يحتاج المترجم إلى معرفة الأمراض المنقولة جنسيا :: سلسلة حتى إذا لم يتم إنشاء مثيل X، لأن الاسم لا تعتمد على حجة قالب T (بقدر المترجم يمكن أن تتحمل).
والكل في الكل، typedefs في فئة أساسية قالب تبدو عديمة الفائدة وليس لاستخدامها في فئة مشتقة. وtypedefs مفيدة للمستخدم، ولكن.
وهذا المفهوم يمكن أن تترافق مع كيفية استخدامنا std::vector<T>
. على سبيل المثال، إذا كان لدينا std::vector<int> Foo
. الآن، قررنا استخدام أي من انها أنواع الأعضاء، دعنا نقول لiterator
. في هذا السيناريو نذكر صراحة
std::vector<int>::iterator foo_iterator;
وبالمثل في قضيتك، من أجل استخدام Vec_t
نوع عضو عام من template <typename T> class A
، تحتاج إلى نعلن ذلك صراحة
A<T>::Vec_t v;
OR
A<int>::Vec_t int_type;