0

まだC++/ boostを掘り下げているので、コメント/フィードバックは大歓迎です。

私はboost::unordered_mapsで遊んでいて、図形を使用して多形の例を作成しました。頭を包み込んだ頃(ほとんど)、boostmulti_indexのmruの例に出くわしました。 http://www.boost.org/doc/libs/1_46_1/libs/multi_index/example/serialization.cpp

その時点で私は思った。うーん、LRUに基づいて値を破棄する固定サイズのマルチインデックスポリモーフィックコンテナで、実装しないのはおかしなことに聞こえます。

    #include <boost/multi_index_container.hpp>
    #include <boost/multi_index/hashed_index.hpp>
    #include <boost/multi_index/identity.hpp>
    #include <boost/multi_index/sequenced_index.hpp>
    #include <boost/shared_ptr.hpp>
    #include <boost/tuple/tuple.hpp>
    #include "boost/tuple/tuple_comparison.hpp"

    enum shape_returns {
        SHAPE_ERROR = -1,
        SHAPE_OK = 0
    };

    // coordinates
    typedef boost::tuples::tuple<int, int, int> ShapeKey;

    class Shape {
    public:
        Shape() : pos() {}
        ~Shape() {}

        virtual int draw() { return SHAPE_ERROR; }

        ShapeKey pos;
    };
    typedef boost::shared_ptr<Shape> Shape_ptr;

    class Circle : public Shape {
    public:
        Circle() {}
        ~Circle() {}

        int radius;

        virtual int draw() { /* draw stuff */ return SHAPE_OK; }
    };
    typedef boost::shared_ptr<Circle> Circle_ptr;

    class Square : public Shape {
    public:
        Square() {}
        ~Square() {}

        int len;

        virtual int draw() { /* draw stuff */ return SHAPE_OK; }
    };
    typedef boost::shared_ptr<Square> Square_ptr;

    using namespace boost::multi_index;

    // multi index tags
    struct seq  {};
    struct hash {};

    class ShapesLRU {
        typedef boost::multi_index::multi_index_container<
          Shape_ptr,
          boost::multi_index::indexed_by<
            boost::multi_index::sequenced<boost::multi_index::tag<seq> >,
            boost::multi_index::hashed_unique<
              boost::multi_index::tag<hash>,
              boost::multi_index::identity<Shape_ptr>
            >
          >
        > shapes_list;

    public:
        typedef typename shapes_list::iterator iterator;
        typedef typename boost::multi_index::index<shapes_list, seq>::type seq_index;
        typedef typename boost::multi_index::index<shapes_list, hash>::type hashed_index;

        ShapesLRU (std::size_t max) : max_shapes(max) {}
        ~ShapesLRU() {}

        void insert(const Shape_ptr item)
        {
            std::pair<typename shapes_list::iterator, bool> ret = shapes.push_front(item);

            if (!ret.second) {
                // new item may be different
                erase(item->pos);
                ret = shapes.push_front(item);
            } else if (shapes.size() > max_shapes) {
                shapes.pop_back();
            }
        }

        typename shapes_list::iterator begin() { return shapes.begin(); }
        typename shapes_list::iterator end() { return shapes.end(); }

        typename hashed_index::iterator hash_begin() { return shapes.get<hash>().begin(); }
        typename hashed_index::iterator hash_end() { return shapes.get<hash>().end(); }

        typename hashed_index::iterator find(const ShapeKey &key)
        {
            Shape_ptr tmp(new Shape());
            tmp->pos = key;

            // XXX why compiler error w/o "using namespace boost::multi_index"
            return shapes.get<hash>().find(tmp);
        }

        void erase(const ShapeKey &key)
        {
            typename hashed_index::iterator itr = find(key);
            // XXX why compiler error w/o "using namespace boost::multi_index"
            shapes.get<hash>().erase(itr);
        }

    private:
        // The multi-indexed data store
        shapes_list shapes;

        // The size of the data store
        std::size_t max_shapes;
    };

    inline std::size_t
    hash_value(const Shape_ptr shape)
    {
        std::size_t seed = 0;

        boost::hash_combine(seed, shape->pos.get<0>());
        boost::hash_combine(seed, shape->pos.get<1>());
        boost::hash_combine(seed, shape->pos.get<2>());

        return seed;
    }

    int
    main()
    {
        ShapesLRU shapes(10);

        Circle_ptr cptr1(new Circle());
        ShapeKey pos1(1, 1, 1);
        cptr1->pos = pos1;
        cptr1->radius = 1;

        Circle_ptr cptr2(new Circle());
        ShapeKey pos2(2, 2, 2);
        cptr2->radius = 2;
        cptr2->pos = pos2;

        shapes.insert(cptr1);

        ShapesLRU::hashed_index::iterator itr = shapes.find(pos1);

        return 0;
    }

たくさんのことをやり遂げた後、私はまだ次の質問を残されています。

  1. insert()で、シーケンスイテレータからhashed_uniqueイテレータを取得して、eraseを直接呼び出す方法はありますか?

  2. findを実装するより良い方法はありますか?ルックアップのためだけにダミーの形状を作成する代わりに、キーだけを使用してboost::unordered_mapのような検索を実行できれば便利です。

  3. get <>の正しいパスは何ですか(コードのXXXコメントを参照)私は正しいことをすべて試した後、ランダムながらくたを試し始めましたが、何もパンアウトされませんでした。

  4. 本当に[]演算子が欲しいのですが、それは道のりだと思います... shape [cptr1-> pos] = cptr1;

  5. 私のhash_index::iteratorからアイテムを取得する(または一般的にこれを理解する)にはどうすればよいですか、それを印刷することは確かに役に立ちませんでした...

p itr $ 1 = {、std :: allocator >>>、boost :: multi_index :: detail ::bucket_array >>>、boost :: shared_ptr、long、boost :: shared_ptr const *、boost :: shared_ptr const&>> = {、std :: allocator >>>、boost :: multi_index :: detail ::bucket_array >>>、boost :: shared_ptr const *、boost :: iterator、long、boost :: shared_ptr const *、boost :: shared_ptr const& > >> = {、std :: allocator >>>、boost :: multi_index :: detail ::bucket_array >>>、boost :: shared_ptr const *、boost :: iterator、long、boost :: shared_ptr const *、boost :: shared_ptr const&> >> = {、std :: allocator >>>、boost :: multi_index :: detail ::bucket_array >> >>、boost :: incrementable、std :: allocator >>>、boost :: multi_index: :detail ::bucket_array >>>、boost :: dereferenceable、std :: allocator>>>、boost :: multi_index :: detail ::bucket_array >>>、boost :: shared_ptr const *、boost :: iterator、long、boost :: shared_ptr const *、boost :: shared_ptr const&>> >>> = { 、std :: allocator >>>、boost :: multi_index :: detail ::bucket_array >>>、boost :: dereferenceable、std :: allocator >> >>、boost :: multi_index :: detail ::bucket_array >>>、 boost :: shared_ptr const *、boost :: iterator、long、boost :: shared_ptr const *、boost :: shared_ptr const&>> >> = {、std :: allocator >> >>、boost :: multi_index :: detail :: bucket_array >>>、boost :: shared_ptr const *、boost :: iterator、long、boost :: shared_ptr const *、boost :: shared_ptr const&> >> = {、long、boost :: shared_ptr const *、boost :: shared_ptr const&>> = {、long、boost :: shared_ptr const *、boost ::shared_ptr const&>> = {、long、boost :: shared_ptr const *、boost :: shared_ptr const&>> = {}、}、}、}、}、}、}、}、}、node = 0x60a010、buckets = 0x7fffffffdd88 }

4

1 に答える 1

2

insert()で、シーケンスイテレータからhashed_uniqueイテレータを取得して、eraseを直接呼び出す方法はありますか?

イテレータプロジェクションを参照してください。

findを実装するより良い方法はありますか?ルックアップのためだけにダミーの形状を作成する代わりに、キーだけを使用してboost::unordered_mapのような検索を実行できれば便利です。

まず第一に、あなたの現在の実装は間違っていると思います:あなたのハッシュされたインデックスはShape_ptr平等に基づいています、それはあなたが求めているものではありません-あなたはに基づいて平等を望んでいますShape::ShapeKey。これを取得するには、インデックスを次のように再定義するだけです。

boost::multi_index::hashed_unique<
  boost::multi_index::tag<hash>,
  boost::multi_index::member<Shape,ShapeKey,&Shape::pos>
>

これを機能させるには、のハッシュを実装する必要があります。ShapeKey演習として残しておきます:-)実装findは次のように簡単です。

hashed_index::iterator find(const ShapeKey &key)
{
    return shapes.get<hash>().find(key);
}

get <>の正しいパスは何ですか(コードのXXXコメントを参照)私は正しいことをすべて試した後、ランダムながらくたを試し始めましたが、何もパンアウトされませんでした。

構文が機能しない理由がわかりません。そうすべき。

本当に[]演算子が欲しいのですが、それは道のりだと思います... shape [cptr1-> pos] = cptr1;

Boost.MultiIndexのインデックスは、andではなくandに基づいてモデル化されます(基本std::setstd::unordered_setstd::map理由std::unordered_mapから、ここで説明する必要はありません)。この同等性を利用して、Boost.MultiIndexを使用してマップのような構造を構築できます。map<T,Q>set<mutable_pair<T,Q>>mutable_pairmutable

私のhash_index::iteratorからアイテムを取得する(または一般的にこれを理解する)にはどうすればよいですか、それを印刷することは確かに役に立ちませんでした...

「印刷」とはどういう意味ですか?

于 2012-05-31T06:13:05.400 に答える