ATL: шаблон узла дерева с использованием CAtlMap
От: neutrino  
Дата: 14.10.02 12:17
Оценка:
задумал написать шаблон узла дерева (напимер файловой системы) с использованием CAtlMap
каждый узел может содержать как данные, так и дочерние узлы (а может и не содержать )
компилятор выдает ошибку C2079 "ATL::CAtlMap<K,V,KTraits,VTraits>::CPair::m_value uses undefined class CTreeNode<KEY,VALUE>"
в чем же проблема, и как ее победить? спасибо



//////////////////////////////////////////////////////////////////////
// TreeNode.h: CTreeNode<KEY, VALUE> template
//////////////////////////////////////////////////////////////////////

#pragma once

#include <atlbase.h>
#include <atlcoll.h>

//////////////////////////////////////////////////////////////////////
// CTreeNode, CTreeIterator interfaces
//////////////////////////////////////////////////////////////////////

template <typename KEY, typename VALUE>
class /*ATL_NO_VTABLE*/ CTreeNode
{
public:
    typedef CTreeNode/*<KEY, VALUE>*/    NODE;
    typedef CAtlMap<KEY, CTreeNode/*NODE*/>        TREE;
    typedef TREE::CPair                PAIR;
// iterator
    class CTreeIterator
    {
    public:
        CTreeIterator(NODE &rNode): m_pMap(rNode.m_pChildren), m_pos(NULL) {}
        ~CTreeIterator() {}
        PAIR* First() { m_pos=NULL; return m_pMap ? Next() : NULL; }
        PAIR* Next() { if(m_pMap) { if(m_pos == NULL) m_pos=m_pMap->GetStartPosition(); return m_pMap->GetNext(m_pos); } else return NULL; }
    protected:
        TREE *m_pMap;
        POSITION m_pos;
    };
// construction/destruction
    CTreeNode(const NODE* = NULL);
    CTreeNode(const NODE &, const NODE* = NULL);
    CTreeNode(const VALUE &, const NODE* = NULL);
    /*virtual*/~CTreeNode();    // no vtable for better perfomance
// operators
    NODE& operator =(const NODE &);
    NODE& operator =(const VALUE &);
    operator VALUE*() const { return m_pValue; }
    operator TREE*() const { return m_pChildren; }
// methods
    bool IsRoot() const { return (m_pParent == NULL); }
    bool IsValue() const { return (m_pValue != NULL); }
    bool IsParent() const { return (m_pChildren != NULL); }

    const NODE* GetParent() const { return m_pParent; }
    const KEY* GetParentsKey() const;                // slow

    size_t GetCount() const;                        // very slow
    size_t GetCountValues() const;                    // very slow

    PAIR* MoveTo(const KEY &, NODE &) const;        // slow
    PAIR* CopyTo(const KEY &, NODE &) const;        // very slow

    PAIR* AddChild(const KEY &rKey, const NODE &rNode);
    PAIR* AddChild(const KEY &rKey, const VALUE &rValue);

    PAIR* FindChild(const KEY &) const;

    bool RemoveChild(const KEY &);
    void RemoveChildren() { RemoveMap(); }
protected:
    bool CreateMap();
    bool CreateValue(const VALUE &rValue);
    void RemoveMap() { if(m_pChildren) { delete m_pChildren; m_pChildren=NULL; } }
    void RemoveValue() { if(m_pValue) { delete m_pValue; m_pValue=NULL; } }
// attributes
    const NODE *m_pParent;
    TREE *m_pChildren;
    VALUE *m_pValue;
};

template <typename KEY, typename VALUE>
CTreeNode<KEY, VALUE>::CTreeNode(const CTreeNode<KEY, VALUE> *pParent)
: m_pParent(pParent)
, m_pChildren(NULL)
, m_pValue(NULL)
{
    ATLTRACE(_T("CTreeNode object 0x%08X constructed, parent is 0x%08X\n"), this, m_pParent);
}

template <typename KEY, typename VALUE>
CTreeNode<KEY, VALUE>::CTreeNode(const CTreeNode<KEY, VALUE> &rNode, const CTreeNode<KEY, VALUE> *pParent)
: m_pParent(pParent)
, m_pChildren(NULL)
, m_pValue(NULL)
{
    ATLTRACE(_T("CTreeNode object 0x%08X constructed, parent is 0x%08X\n"), this, m_pParent);
    operator=(rNode);
}

template <typename KEY, typename VALUE>
CTreeNode<KEY, VALUE>::CTreeNode(const VALUE &rVal, const CTreeNode<KEY, VALUE> *pParent)
: m_pParent(pParent)
, m_pChildren(NULL)
, m_pValue(NULL)
{
    ATLTRACE(_T("CTreeNode object 0x%08X constructed, parent is 0x%08X\n"), this, m_pParent);
    operator=(rVal);
}

template <typename KEY, typename VALUE>
CTreeNode<KEY, VALUE>::~CTreeNode()
{
    RemoveMap();
    RemoveValue();
    ATLTRACE(_T("CTreeNode object 0x%08X destructed\n"), this);
}

template <typename KEY, typename VALUE>
CTreeNode<KEY, VALUE>& CTreeNode<KEY, VALUE>::operator =(const VALUE &rValue)
{
    CreateValue(rValue);
    return *this;
}

template <typename KEY, typename VALUE>
CTreeNode<KEY, VALUE>& CTreeNode<KEY, VALUE>::operator =(const CTreeNode<KEY, VALUE> &rNode)
{
    if(rNode.m_pValue) CreateValue(*rNode.m_pValue);
    else RemoveValue();
    return *this;
}

template <typename KEY, typename VALUE>
bool CTreeNode<KEY, VALUE>::CreateMap()
{
    if(!m_pChildren) m_pChildren=new TREE;
    return (m_pChildren != NULL);
}

template <typename KEY, typename VALUE>
bool CTreeNode<KEY, VALUE>::CreateValue(const VALUE &rValue)
{
    if(!m_pValue) m_pValue=new VALUE;
    if(m_pValue) *m_pValue=rValue;
    return (m_pValue != NULL);
}

template <typename KEY, typename VALUE>
size_t CTreeNode<KEY, VALUE>::GetCount() const
{
    size_t nCount=1;    // this
    CTreeIterator it(const_cast<NODE>(*this));
//    CTreeIterator it(*this);
    PAIR *pSubPair=it.Next();
    while(pSubPair)
    {
        nCount+=pSubPair->m_value.GetCount();
        pSubPair=it.Next();
    }
    return nCount;
}

template <typename KEY, typename VALUE>
size_t CTreeNode<KEY, VALUE>::GetCountValues() const
{
    size_t nCount=0;
    if(m_pValue) nCount++;    // this
    CTreeIterator it(const_cast<NODE>(*this));
//    CTreeIterator it(*this);
    PAIR *pSubPair=it.Next();
    while(pSubPair)
    {
        nCount+=pSubPair->m_value.GetCountValues();
        pSubPair=it.Next();
    }
    return nCount;
}

template <typename KEY, typename VALUE>
CTreeNode<KEY, VALUE>::PAIR* CTreeNode<KEY, VALUE>::AddChild(const KEY &rKey, const CTreeNode<KEY, VALUE> &rNode)
{
    return CreateMap() ? m_pChildren->GetAt(m_pChildren->SetAt(rKey, rNode)) : NULL;
}

template <typename KEY, typename VALUE>
CTreeNode<KEY, VALUE>::PAIR* CTreeNode<KEY, VALUE>::AddChild(const KEY &rKey, const VALUE &rValue)
{
    NODE node(rValue);
    return AddChild(rKey, node);
}

template <typename KEY, typename VALUE>
CTreeNode<KEY, VALUE>::PAIR* CTreeNode<KEY, VALUE>::FindChild(const KEY &rKey) const
{
    return m_pChildren ? m_pChildren->Lookup(rKey) : NULL;
}

template <typename KEY, typename VALUE>
bool CTreeNode<KEY, VALUE>::RemoveChild(const KEY &rKey)
{
    if(!m_pChildren) return false;
    bool bOk=m_pChildren->RemoveKey(rKey);
    if(m_pChildren.IsEmpty()) RemoveMap();
    return bOk;
}

template <typename KEY, typename VALUE>
CTreeNode<KEY, VALUE>::PAIR* CTreeNode<KEY, VALUE>::CopyTo(const KEY& rKey, CTreeNode<KEY, VALUE> &rParent) const
{
    PAIR *pNewPair=rParent.AddChild(rKey, *this);
    if(pNewPair)
    {
        CTreeIterator it(const_cast<NODE>(*this));
//        CTreeIterator it(*this);
        PAIR *pSubPair=it.Next();
        while(pSubPair)
        {
            pSubPair->m_value.CopyTo(pSubPair->m_key, pNewPair->m_value);
            pSubPair=it.Next();
        }
    }
    return pNewPair;
}

template <typename KEY, typename VALUE>
CTreeNode<KEY, VALUE>::PAIR* CTreeNode<KEY, VALUE>::MoveTo(const KEY& rKey, CTreeNode<KEY, VALUE> &rParent) const
{
    NODE *pOldParent=GetParent();
    KEY *pOldKey=GetParentsKey();
    PAIR *pPair=NULL;
    if(pOldParent && pOldKey)
    {
        // removing from old parent
        pOldParent->RemoveChild(*pOldKey);
        // adding to new parent
        pPair=rParent.AddChild(rKey, *this);
    }
    return pPair;
}

template <typename KEY, typename VALUE>
const KEY* CTreeNode<KEY, VALUE>::GetParentsKey() const
{
    NODE *pParent=GetParent();
    if(!pParent) return NULL;

    CTreeIterator it(const_cast<NODE>(*pParent));
//    CTreeIterator it(*pParent);
    PAIR *pPair=it.Next();
    while(pPair)
    {
        if(pPair->m_value == *this) break;
        pPair=it.Next();
    }
    return pPair ? &pPair->m_key : NULL;
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.