【发布时间】:2012-10-02 22:39:20
【问题描述】:
我已经实现了这个侵入式链表:
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::node 是在定义 MyEntry2 之前获取的:
prog.cpp:33:27: error: incomplete type 'MyEntry2' used in nested name specifier
prog.cpp:33:41: error: template argument 2 is invalid
这个有问题的布局实际上没有任何实际语义,这只是我发现的一个理论问题,它可能会限制通用链表的可用性。
有什么方法可以解决这个问题而不会使列表变得更加不切实际?
EDIT:这里所有数据结构的布局都是完全定义好的。这是因为 LinkedList 的数据成员不依赖有问题的 NodeMember 模板参数;只有函数可以。问题似乎是该语言要求知道 &MyEntry2::node ,即使它当时并不真正需要知道。
EDIT:必须可以使用此通用列表将结构添加到两个或多个列表中;这是 NodeMember 模板参数的用途 - 它指定要使用条目中的哪个 LinkedListNode。
【问题讨论】:
-
我认为当时确实需要知道它。您正在引用一个尚未声明的成员,仅仅因为您没有创建结构的实例并不意味着您的编译器在解析该行时没有寻找该成员。当我只使用它的标识符而不是它的一个成员时,我只使用了结构的前向声明。也许我错了,但是循环依赖也让我困惑=P
-
你也可以通过继承来实现这些钩子。这将解决问题并且更清洁 imo,无论如何它都是侵入性的。
-
另外,您能否告诉我们您为什么不想使用 STL 列表?
-
@CrazyCasta 侵入性列表有很多理由。我认为这里没有必要。
-
@CrazyCasta 这个问题不是关于侵入式与非侵入式数据结构的。我的问题是关于侵入性列表,无论出于何种原因。我没有研究过 boost intrusive,但我怀疑他们也遇到了同样的问题。
标签: c++ templates linked-list circular-dependency intrusive-containers