1

私は「ノード」と呼ばれるこのクラスを持っています。名前を「Tree」に変更することを検討してきましたが、どちらの名前でも同じくらい意味があります。このクラスは、ジェネリックツリーコンテナを実装します。各ノードには、任意の数の子を含めることができます。クラスの基本的なヘッダー定義は次のとおりです。

template<class Elem>
class Node
{
public:
    Node();
    ~Node();
    Node(const Elem& value);
    Node(const Node& rNode);
    const Elem& operator*() const;
    Elem& operator*();
    Elem* operator->();
    void operator=(const Elem& rhs);
    Node* addChild(const Elem& value);
    Node* addChild(Node childNode);
    Node* addChild(Node* pChildNode);
    HRESULT removeNode(DFSIterator<Node>& iter);

    template <class Node, class List, class Iter> friend class DFSIterator;

private:
    bool hasChild() const;

    Node* m_pParentNode;
    Elem m_value;
    std::vector<Node*> m_childList;
    static std::set<Node*> sNodeSet;
};

DFSIteratorのヘッダー定義は次のとおりです。

template<class Item, 
         class List = std::vector<Item*>, 
         class Iter = typename std::vector<Item*>::iterator>
class DFSIterator
{
public:
    DFSIterator(Item& rRootNode);
    ~DFSIterator();
    DFSIterator* begin();
    DFSIterator* operator++();
    Item& operator*() const;
    Item* operator->() const;
    bool operator!=(const DFSIterator& rhs) const;
    bool isDone() const;
    operator bool() const {return !isDone();}

private:
    template <class Node> friend class Node;

    void initChildListIterator(Item* currentNode);

    bool m_bIsDone;
    Item* m_pRootNode;
    Item* m_pCurrentNode;
    ChildListIterator<Item>* m_pCurrentListIter;
    std::map<Item*, ChildListIterator<Item, List, Iter>*>  m_listMap;
};

ItemのイテレータのエイリアスですNode<Elem>

私が抱えている問題は、ユーザーがSTLコンテナーと同様の方法で宣言できるこのツリーのイテレーターを定義したいということです。typedefステートメントをのようtypedef DFSIterator<Node<Elem>> dfs_iterator;に配置するとうまくいくと思っていました。しかし、これらのステートメントをヘッダーに追加すると、error C2512<Item>: no appropriate default constructor available.どこに行って使用しようとしても、次のエラーが発生します。

したがって、今のところ、イテレータを宣言するには、ツリーのルートノードから開始したくない場合DFSIterator<Node<DataMap>> dfsIter = rRootNode.begin();のようなことを行う必要があります。DFSIterator<Node<DataMap>> dfsIter(rNode);私がやりたいのは、もっと似たようなものNode<DataMap>::dfs_iterator it = rRootNode.begin()です。私が行方不明になっているこれを行う方法はありますか?

注:この実装に関する他のいくつかの変更を行いたいと思います。ユーザーがノード要素をaddChild()メソッドに渡してほしくないのです。むしろ、ノードを指しているイテレータをユーザーに渡してもらいたいです。

4

1 に答える 1

1

Node内でdfs_iteratorを定義すると、基本的に次のように使用できます。

template<class Elem>
class Node
{
public:
    typedef Node<Elem> Item;

    template<
        class List = std::vector<Item*>, 
        class Iter = typename std::vector<Item*>::iterator
    > class dfs_iterator;

     .
     .
     .
};

template<class Elem>
template<class List, class Iter>
class Node<Elem>::dfs_iterator
{
public:

    .
    .
    .
};

と使用

Node<DataMap>::dfs_iterator<> it = rRootNode.begin();

唯一の違いは、dfs_iteratorはテンプレートであるため、両方をデフォルトにできる場合でも、テンプレートパラメーターを指定する必要があることです。

于 2013-01-23T16:08:30.820 に答える