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;
}
Re: ATL: шаблон узла дерева с использованием CAtlMap
От: Алекс Россия http://wise-orm.com
Дата: 14.10.02 12:24
Оценка:
Здравствуйте 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'ы за определение класса
Re[2]: ATL: шаблон узла дерева с использованием CAtlMap
От: neutrino  
Дата: 14.10.02 12:35
Оценка:
Здравствуйте Алекс, Вы писали:

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>>[/ccode]

А>Может уберешь typedef'ы за определение класса


во-первых typedef-ы зависят от параметров, инициализирующих класс, т.е. должны быть внутри,
а во-вторых они нужны только для уменьшения писанины, их можно вообще убрать, ничего не изменится...
Re[3]: ATL: шаблон узла дерева с использованием CAtlMap
От: Алекс Россия http://wise-orm.com
Дата: 14.10.02 12:46
Оценка:
Здравствуйте neutrino, Вы писали:

хъ

N>во-первых typedef-ы зависят от параметров, инициализирующих класс, т.е. должны быть внутри,

N>а во-вторых они нужны только для уменьшения писанины, их можно вообще убрать, ничего не изменится...

Ну ты столько кода привел, что ничего без пол литры не разберешь! Ты привиди где конкретно ругается!
Re[4]: ATL: шаблон узла дерева с использованием CAtlMap
От: neutrino  
Дата: 14.10.02 12:53
Оценка:
Здравствуйте Алекс, Вы писали:

А>Здравствуйте neutrino, Вы писали:


А>хъ


N>>во-первых typedef-ы зависят от параметров, инициализирующих класс, т.е. должны быть внутри,

N>>а во-вторых они нужны только для уменьшения писанины, их можно вообще убрать, ничего не изменится...

А>Ну ты столько кода привел, что ничего без пол литры не разберешь! Ты привиди где конкретно ругается!


я широким жестом бросил весь файл, берешь его отсюда и компилируешь, разбираешься, находишь правильное решение
а ругается как только начинаешь использовать этот шаблон, например:
CTreeNode <CAtlString, CSomeClass> g_someObject;

сразу отправляет в
...\Microsoft Visual Studio .NET\Vc7\atlmfc\include\atlcoll.h(1939)
Re[5]: ATL: шаблон узла дерева с использованием CAtlMap
От: Алекс Россия http://wise-orm.com
Дата: 15.10.02 03:29
Оценка:
Здравствуйте neutrino, Вы писали:

N>Здравствуйте Алекс, Вы писали:


хъ

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

N>а ругается как только начинаешь использовать этот шаблон, например:
N>
CTreeNode <CAtlString, CSomeClass> g_someObject;

N>сразу отправляет в
N>
...\Microsoft Visual Studio .NET\Vc7\atlmfc\include\atlcoll.h(1939)


Ну не знаю! У меня 7-ки нет — проверить не могу. Могу только посоветовать: потихоньку убирай не нужные фитчи, упрощай код. Минимизирую его до тех пор, пока ошибка не перестанет появлятся. Затем начинай добавлять удаленные фитчи. И так далее.

Короче, продолжаться это должно до тех пор, пока не выяснишь причину.
Re[6]: ATL: шаблон узла дерева с использованием CAtlMap
От: neutrino  
Дата: 15.10.02 06:10
Оценка:
Здравствуйте Алекс, Вы писали:

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


ето все понятно, проблемы возникают, как только появляется метод, возвращающий PAIR* (CAtlMap<KEY, CTreeNode>::CPair*). а при переборе под-узлов необходимо иметь доступ как к значению, так и к ключу (не правда ли?).
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.