كيفية إنشاء هيكل يحتوي على قائمة نفسها؟

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

  •  06-09-2019
  •  | 
  •  

سؤال

أريد إنشاء بنية تحتوي على قائمة بنفس البنية مثل هذا:

#include <list>
struct Url
{
    CString strUrl;
    std::list<Url> children;
};

int main()
{
    Url u1, u2;
    u1.children.push_back(u2);
}

هذا الرمز ليس تجميع. ولكن عندما استبدل std::list مع std::vector انها تعمل بشكل جيد. كيف يمكنني جعل هذا العمل مع std::list?

نافذة الإخراج تحتوي على الخطأ التالي.

c:\program files\microsoft visual studio\vc98\include\list(29) : error C2079: '_Value' uses undefined struct 'Url'
        E:\test\Test.cpp(23) : see reference to class template instantiation 'std::list<struct Url,class std::allocator<struct Url> >' being compiled
c:\program files\microsoft visual studio\vc98\include\functional(185) : error C2079: 'value' uses undefined struct 'Url'
        c:\program files\microsoft visual studio\vc98\include\list(285) : see reference to class template instantiation 'std::binder2nd<struct std::not_equal_to<struct Url> >' being compiled
        E:\test\Test.cpp(23) : see reference to class template instantiation 'std::list<struct Url,class std::allocator<struct Url> >' being compiled
هل كانت مفيدة؟

المحلول

إذا كنت بحاجة إلى جدولة لما يبدو أنه علة VC6، فقم بإنشاء القائمة ديناميكيا:

#include <list>
#include <string>     // I don't use MFC

struct Url
{
    std::string strUrl;
    std::list<Url> * children;

    Url() {
       children = new std::list <Url>;
    }

    ~Url() {
        delete children;
    }
};

int  main()
{
    Url u1, u2;
    u1.children->push_back(u2);
}

وقد سئل البعض عن سبب السماح قوائم نفس النوع حيث يسمح بالأعضاء (وفي رأيي هم) عندما

Url array[5]; 

على سبيل المثال، لن يكون العضو. لا أستطيع أن أجد أي شيء في المعيار أيضا، لكن sizeof( std:;list <T>) لا يعتمد على شيء ما هي قائمة. لنفترض أن قائمة تم تنفيذها ك (بعض Pseudo C ++ هنا):

list <T> {
   listEntry <T> * first;
};

ثم لا يوجد حجم غير معروف للتعامل معه. النظر في رمز الحد الأدنى التالي الذي يعالج مشكلة المشوضين:

template <typename T> struct A {
};

struct B {
    A <B> b;
};

لا أستطيع أن أرى أي سبب محتمل أن هذا لا ينبغي أن يكون قانونيا.

نصائح أخرى

هل يمكن أن تخبرنا ما هو التحويل البرمجي الذي تستخدمه؟ لا يوجد شيء بطبيعته مع ما تفعله. حاولت ما يلي على VS2008 SP1 وتجميع أي مشكلة

#include <list>

struct Url
{
    std::string name;
    std::list<Url> children;
};

int _tmain(int argc, _TCHAR* argv[])
{
    Url u1,u2;
    u1.children.push_back(u2);
    return 0;
}

هل ربما تنسى أن تدرج قائمة؟

تعديل

يستخدم OP Visual Studio 6.0 ونيل كان قادرا على تأكيد أنه في الواقع خطأ في VS6

خلافا للمطالبات في الإجابات الأخرى، فهي في الواقع ليس قانونية لتثبيت أي حاوية قياسية، بما في ذلك std::list, مع نوع غير مكتمل. (ل مناقشة هذا، انظر على سبيل المثال كيف يمكن استخدام نوع غير مكتمل كمعلمة قالب للمتجه هنا؟)

هذا الشرط يحصل فقط استرخاء في C ++ 17 ل std::forward_list, std::list و std::vector. وبعد بالنسبة لأي معيار سابق، فإن التعليمات البرمجية الأصلية تعمل مع الإصدارات الأحدث من VC و GCC هي امتداد غير قياسي. هذا ينطبق أيضا على ملاحظاتك مع std::vector.

في ما قبل + + 17، لم يكن لديك std::list من بعض الفئة T كعضو من الطبقة المذكورة، تحتاج إلى حلول مثل std::list<T*> أو استخدم مكتبة Bost.container، والتي تنفذ بالفعل المتطلبات المريحة بالفعل.

لاحظ أنه حتى في C ++ 17، يمكنك فقط إنشاء قالب الفصل نفسه بنوع غير مكتمل. يجب أن يكون هذا النوع مكتمل عند إنشاء مثيل لأي عضو.

مثيرة للاهتمام - أنت تحاول إنشاء vector أو list من نوع غير مكتمل. من نظرة سريعة على المعيار، لا يمكنني العثور على أي شيء يقول ما إذا كان هذا هو أو ليس من المفترض أن يسمح لأنواع الحاويات المضمنة في المكتبة القياسية C ++. يبدو أن الحكم معقولا:

لماذا قد لا يسمح به: لا يمكنك إعلان كائن من النوع X داخل تعريف X.

على سبيل المثال فشل التعليمة البرمجية التالية في الترجمة لأنه سينشئ بنية بيانات عميقة بلا حدود:

struct X {
    X x;
};

لماذا قد يسمح: معظم الحاويات لا يمكن تغييرها، مما يستلزم مستوى غير مباشر (المؤشرات) عناصر البيانات الفعلية في الممارسة العملية. من القانوني أن تعلن مؤشرX داخل تعريف X.

كما تقترح الفقرة الأخيرة، فإن الطريقة المعتادة للتغلب على هذه المشكلة هي استخدام المؤشرات أو الإشارات إلى X. وبعد على سبيل المثال، القشريتان التاليان تجميعها على ما يرام:

struct Y {
    Y* y;
};

struct Z {
    std::list<Z*> zl;
    std::vector<Z*> zv;
};

هل أي شخص (موافق، أقصد LITB :-P) تعرف على المتطلبات بالفعل لأنواع الحاويات القياسية؟

يجمع الرمز جيدا مع GCC 4.4 وينفذ تماما. MSVC ++ قبل الإصدار 7، لم يكن متوافق مع المعايير تماما. يجب أن تفكر في استخدام مترجم أحدث.

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