задумал написать шаблон узла дерева (напимер файловой системы) с использованием 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;
}
Здравствуйте neutrino, Вы писали:
N>задумал написать шаблон узла дерева (напимер файловой системы) с использованием CAtlMap
N>каждый узел может содержать как данные, так и дочерние узлы (а может и не содержать
)
N>компилятор выдает ошибку C2079 "ATL::CAtlMap<K,V,KTraits,VTraits>::CPair::m_value uses undefined class CTreeNode<KEY,VALUE>"
N>в чем же проблема, и как ее победить? спасибо
N>
N>
N>//////////////////////////////////////////////////////////////////////
N>// TreeNode.h: CTreeNode<KEY, VALUE> template
N>//////////////////////////////////////////////////////////////////////
N>#pragma once
N>#include <atlbase.h>
N>#include <atlcoll.h>
N>//////////////////////////////////////////////////////////////////////
N>// CTreeNode, CTreeIterator interfaces
N>//////////////////////////////////////////////////////////////////////
N>template <typename KEY, typename VALUE>
N>class /*ATL_NO_VTABLE*/ CTreeNode
N>{
N>public:
N> typedef CTreeNode/*<KEY, VALUE>*/ NODE;
N> typedef CAtlMap<KEY, CTreeNode/*NODE*/> TREE;
N> typedef TREE::CPair PAIR;
[]
N>
Может уберешь typedef'ы за определение класса
Здравствуйте neutrino, Вы писали:
хъ
N>во-первых typedef-ы зависят от параметров, инициализирующих класс, т.е. должны быть внутри,
N>а во-вторых они нужны только для уменьшения писанины, их можно вообще убрать, ничего не изменится...
Ну ты столько кода привел, что ничего без пол литры не разберешь!

Ты привиди где конкретно ругается!
Здравствуйте Алекс, Вы писали:
А>Здравствуйте neutrino, Вы писали:
А>хъ
N>>во-первых typedef-ы зависят от параметров, инициализирующих класс, т.е. должны быть внутри,
N>>а во-вторых они нужны только для уменьшения писанины, их можно вообще убрать, ничего не изменится...
А>Ну ты столько кода привел, что ничего без пол литры не разберешь!
Ты привиди где конкретно ругается!
я широким жестом

бросил весь файл, берешь его отсюда и компилируешь, разбираешься, находишь правильное решение

а ругается как только начинаешь использовать этот шаблон, например:
CTreeNode <CAtlString, CSomeClass> g_someObject;
сразу отправляет в
...\Microsoft Visual Studio .NET\Vc7\atlmfc\include\atlcoll.h(1939)
Здравствуйте neutrino, Вы писали:
N>Здравствуйте Алекс, Вы писали:
хъ
N>я широким жестом
бросил весь файл, берешь его отсюда и компилируешь, разбираешься, находишь правильное решение
N>а ругается как только начинаешь использовать этот шаблон, например:
N>CTreeNode <CAtlString, CSomeClass> g_someObject;
N>сразу отправляет в
N>...\Microsoft Visual Studio .NET\Vc7\atlmfc\include\atlcoll.h(1939)
Ну не знаю! У меня 7-ки нет — проверить не могу. Могу только посоветовать: потихоньку убирай не нужные фитчи, упрощай код. Минимизирую его до тех пор, пока ошибка не перестанет появлятся. Затем начинай добавлять удаленные фитчи.

И так далее.
Короче, продолжаться это должно до тех пор, пока не выяснишь причину.
Здравствуйте Алекс, Вы писали:
А>Ну не знаю! У меня 7-ки нет — проверить не могу. Могу только посоветовать: потихоньку убирай не нужные фитчи, упрощай код. Минимизирую его до тех пор, пока ошибка не перестанет появлятся. Затем начинай добавлять удаленные фитчи.
И так далее.
Короче, продолжаться это должно до тех пор, пока не выяснишь причину.
ето все понятно, проблемы возникают, как только появляется метод, возвращающий PAIR* (CAtlMap<KEY, CTreeNode>::CPair*). а при переборе под-узлов необходимо иметь доступ как к значению, так и к ключу (не правда ли?).