私はこの邪魔なリンクリストを実装しました:
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);
相互のリストを含む2つのオブジェクトが必要になるまで、問題なく機能します。
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は1つのMyEntry1のリストにのみ表示できます。とその逆。ただし、MyEntry2が定義される前にメンバーポインタ&MyEntry2 :: nodeが取得されるため、これはコンパイルされません。
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を認識していることを要求していることのようです。
編集:この汎用リストを使用して、構造を2つ以上のリストに追加できる必要があります。これがNodeMemberテンプレートパラメータの目的です。エントリ内のどのLinkedListNodeを使用するかを指定します。