0

木を作ろうとしています。私の最初の要件は、ツリー レベル内のオブジェクトがその挿入順序で並べられることです。

最初の試みとして、stl ベクトル クラスを使用しました。

#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;
}

この小さなプログラムは正常にコンパイルされ、期待どおりに実行されます。

さらに一歩進んで、名前でツリー レベルのオブジェクトにアクセスする機能を追加したいので、ブースト マルチ インデックスを使用してみたので、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

誰かがこの相互依存を解決するのを手伝ってくれませんか?

どうもありがとうございました。

よろしくお願いします

James Hopkin のおかげで、プログラムが部分的に動作するようになりました。

#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;
}

ここで、複数インデックス itrerator によって取得されたオブジェクトに要素を追加するために、replace/modify メソッドで作業する必要があります。

どうもありがとうございました。

4

2 に答える 2

2

typedef での使用がNode::nameそのエラーを引き起こしているようです。おそらく、非メンバー関数を作成して aNodeの名前にアクセスし、代わりにそれを使用できます。

于 2012-06-01T11:23:08.443 に答える
0

Boost.PropertyTree をご覧になりましたか?

于 2012-06-01T16:46:09.003 に答える