2012-06-01 54 views
0

我正在嘗試創建一棵樹。我的第一個要求是,樹級中的對象按其插入順序排序。如何使用boost多索引容器創建樹

作爲第一次嘗試我用STL的vector類:

#include <vector> 
#include <iostream> 
#include <string> 

class Node; 
typedef std::vector<Node> NodeList; 

class Node 
{ 
public: 
    Node(const std::string& name, int val=0): name_(name), value_(val), list_() {} 
    Node(const Node& nd): name_(nd.name_), value_(nd.value_), list_(nd.list_) {} 
    Node& operator=(const Node& nd) 
    { 
     name_ = nd.name_; 
     value_ = nd.value_; 
     list_ = nd.list_; 
     return *this; 
    } 
    const std::string& name(void) const {return name_;} 
    NodeList& list(void) {return list_;} 
    const NodeList& list(void) const {return list_;} 
    int value(void) const {return value_;} 
    void value(int val) {value_ = val;} 
private: 
    std::string name_; 
    int value_; 
    NodeList list_; 
}; 

std::ostream& operator<<(std::ostream& os, const Node& nd) 
{ 
    os << nd.name() << "=\"" << nd.value() << "\""; 
    return os; 
} 

std::ostream& operator<<(std::ostream& os, const NodeList& ndlst) 
{ 
    for(NodeList::const_iterator it = ndlst.begin(); it < ndlst.end(); it++) 
    { 
     os << ' ' << *it; 
    } 
    return os; 
} 

int main() 
{ 
    std::cout << "Creating a little tree..." << std::endl; 
    Node a("ROOT", 1); 
    a.list().push_back(Node("LEVEL1_1", 21)); 
    a.list().push_back(Node("LEVEL1_2", 22)); 
    a.list().push_back(Node("LEVEL1_3", 23)); 
    a.list().push_back(Node("LEVEL1_4", 24)); 
    a.list().at(2).list().push_back(Node("LEVEL2_1", 231)); 
    std::cout << "Done. Now let's see some values." << std::endl; 
    std::cout << "root: " << a.value() << ", root->node2: " 
       << a.list().at(1).value() 
       << ", root->node3->node1: " 
       << a.list().at(2).list().at(0).value() 
       << std::endl; 
    std::cout << "Ok, now let's use our '<<' operators." << std::endl; 
    std::cout << a << std::endl; 
    std::cout << a.list() << std::endl; 
    return 0; 
} 

這個小程序編譯確定,按照預期執行。

作爲了一步,我想補充訪問其名稱樹級別對象的能力,所以我tryed使用boost多指標,所以我修改了Node類,如下所示:

class Node; 
struct Name{}; 


typedef boost::multi_index::multi_index_container< 
    Node, 
    boost::multi_index::indexed_by< 
     boost::multi_index::random_access<>, 
     boost::multi_index::hashed_non_unique< 
      boost::multi_index::tag<Name>, 
      boost::multi_index::const_mem_fun<Node, const std::string&, &Node::name> 
     > 
    > 
> NodeList; 


class Node 
{ 
public: 
    Node(const std::string& name, int val=0): name_(name), value_(val), list_() {} 
    Node(const Node& nd): name_(nd.name_), value_(nd.value_), list_(nd.list_) {} 
    Node& operator=(const Node& nd) 
    { 
     name_ = nd.name_; 
     value_ = nd.value_; 
     list_ = nd.list_; 
     return *this; 
    } 
    const std::string& name(void) const {return name_;} 
    int value(void) const {return value_;} 
    void value(int val) {value_ = val;} 
    NodeList& list(void) {return list_;} 
    const NodeList& list(void) const {return list_;} 
private: 
    std::string name_; 
    int value_; 
    NodeList list_; 
}; 

但它根本不能編譯。使用gnu g ++版本4.6.1第一個錯誤是

tree.cpp:19:65: error: incomplete type 'Node' used in nested name specifier 

有人可以幫我解決這種相互依賴嗎?

非常感謝。

問候

感謝詹姆斯霍普金,我有計劃部分工作:

#include <boost/multi_index_container.hpp> 
#include <boost/multi_index/random_access_index.hpp> 
#include <boost/multi_index/hashed_index.hpp> 
#include <boost/multi_index/identity.hpp> 
#include <boost/multi_index/global_fun.hpp> 
#include <iostream> 
#include <string> 

class Node; 
struct Name{}; 
const std::string& getNodeName(const Node& nd); 


typedef boost::multi_index::multi_index_container< 
    Node, 
    boost::multi_index::indexed_by< 
     boost::multi_index::random_access<>, 
     boost::multi_index::hashed_non_unique< 
      boost::multi_index::tag<Name>, 
      boost::multi_index::global_fun<const Node&, const std::string&, &getNodeName> 
     > 
    > 
> NodeList; 


class Node 
{ 
public: 
    Node(const std::string& name, int val=0): name_(name), value_(val), list_(new NodeList) {} 
    Node(const Node& nd): name_(nd.name_), value_(nd.value_), list_(new NodeList(*nd.list_)) {} 
    virtual ~Node() {delete list_;} 
    Node& operator=(const Node& nd) 
    { 
     name_ = nd.name_; 
     value_ = nd.value_; 
     *list_ = *nd.list_; 
     return *this; 
    } 
    const std::string& name(void) const {return name_;} 
    int value(void) const {return value_;} 
    void value(int val) {value_ = val;} 
    NodeList& list(void) {return *list_;} 
    const NodeList& list(void) const {return *list_;} 
    friend const std::string& getNodeName(const Node& nd); 
private: 
    std::string name_; 
    int value_; 
    NodeList* list_; 
}; 



const std::string& getNodeName(const Node& nd) 
{ 
    return nd.name_; 
} 



std::ostream& operator<<(std::ostream& os, const Node& nd) 
{ 
    os << nd.name() << "=\"" << nd.value() << "\""; 
    return os; 
} 



std::ostream& operator<<(std::ostream& os, const NodeList& ndlst) 
{ 
    for(NodeList::const_iterator it = ndlst.begin(); it < ndlst.end(); it++) 
    { 
     const Node& nd = *it; 
     os << ' ' << nd; 
    } 
    return os; 
} 



int main() 
{ 
    std::cout << "Creating a little tree..." << std::endl; 
    Node a("ROOT", 1); 
    a.list().push_back(Node("LEVEL1_1", 21)); 
    a.list().push_back(Node("LEVEL1_2", 22)); 
    a.list().push_back(Node("LEVEL1_3", 23)); 
    a.list().push_back(Node("LEVEL1_4", 24)); 
    // a.list().at(2).list().push_back(Node("LEVEL2_1", 231)); // First call to "at()" returns a read-only iterador so I can't append elements to its pointed object. 
    std::cout << "Done. Now let's see some values." << std::endl; 
    std::cout << "root: " << a.value() << ", root->node2: " 
       << a.list().at(1).value() << std::endl; 
      /* << ", root->node3->node1: " << a.list().at(2).list().at(0).value() 
       << std::endl; */ 
    std::cout << "Ok, now let's use our '<<' operators." << std::endl; 
    std::cout << a << std::endl; 
    std::cout << a.list() << std::endl; 
    return 0; 
} 

現在我必須替換/修改方法工作,以元素添加到由多檢索的對象-dex指示器。

非常感謝。

+0

您是否在某處定義了'NodeBase'。你甚至沒有告訴Node節點繼承自NodeBase – mistapink

+0

Ups,這是通過使用基類節點列表解決它失敗的嘗試的複製粘貼錯誤。編輯並更正。 – Patxitron

回答

2

看起來在typedef中使用Node::name會導致該錯誤。也許你可以創建一個非成員函數來訪問Node的名字並使用它。

0

你看過Boost.PropertyTree嗎?

+0

我會看看它。謝謝。 – Patxitron