задумал написать шаблон узла дерева (напимер файловой системы) с использованием 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;
}