我實現了這個侵入鏈表:C++介入式鏈表循環依賴
template <class Entry>
struct LinkedListNode {
Entry *next;
Entry *prev;
};
template <class Entry, LinkedListNode<Entry> Entry::*NodeMember>
class LinkedList {
public:
void init();
bool isEmpty() const;
Entry * first() const;
Entry * last() const;
Entry * next (Entry *e) const;
Entry * prev (Entry *e) const;
void prepend (Entry *e);
void append (Entry *e);
void insertBefore (Entry *e, Entry *target);
void insertAfter (Entry *e, Entry *target);
void remove (Entry *e);
public:
Entry *m_first;
Entry *m_last;
};
...
template <class Entry, LinkedListNode<Entry> Entry::*NodeMember>
inline Entry * LinkedList<Entry, NodeMember>::next (Entry *e) const
{
return (e->*NodeMember).next;
}
...
它可以像這樣使用:
struct MyEntry {
int value;
LinkedListNode<MyEntry> list_node;
};
LinkedList<MyEntry, &MyEntry::list_node> list;
list.init();
MyEntry entry1, entry2;
entry1.value = 3;
list.append(&entry1);
entry2.value = 5;
list.prepend(&entry2);
它的工作原理沒事,直到你需要兩個對象其中包含彼此的名單:
struct MyEntry2;
struct MyEntry1 {
int value;
LinkedListNode<MyEntry1> node;
LinkedList<MyEntry2, &MyEntry2::node> list;
};
struct MyEntry2 {
int value;
LinkedListNode<MyEntry2> node;
LinkedList<MyEntry1, &MyEntry1::node> list;
};
每個MyEntry1持有MyEntry2的列表,每個MyEntry2ç一個只出現在一個MyEntry1的列表中;和相反。然而,這並不能編譯,因爲成員指針& MyEntry2 ::節點MyEntry2之前拍攝的定義:
prog.cpp:33:27: error: incomplete type 'MyEntry2' used in nested name specifier
prog.cpp:33:41: error: template argument 2 is invalid
確實沒有任何實際的語義這個問題的佈局,它僅僅是一個理論問題我發現哪些可能會限制通用鏈表的可用性。
有沒有解決這個問題的方法,它不會讓列表變得更加不切實際?
編輯:這裏所有數據結構的佈局是完全定義的。這是因爲LinkedList的數據成員不依賴於有問題的NodeMember模板參數;只有功能。問題似乎在於,語言要求即使不需要知道MyEntry2 :: node,也要知道MyEntry2 :: node。
編輯:必須可以使用此通用列表將結構添加到兩個或多個列表中;這是NodeMember模板參數的用途 - 它指定要使用條目中的哪個LinkedListNode。
我認爲它實際上並不需要的時間是已知的。您正在引用尚未聲明的成員,僅僅因爲您沒有創建該結構的實例並不意味着您的編譯器在解析該行時未查找該成員。當我僅使用它的標識符時,我只使用了結構的前向聲明,而不是它的一個成員。也許我錯了,但循環依賴也混淆了我= P –
你也可以通過繼承來實現鉤子。這將解決這個問題,無論如何,它都是乾淨利落的。 – pmr
另外,你能否告訴我們爲什麼你不想使用STL列表? – CrazyCasta