Boost组件multi_index_container实例(续5)

晨曦之光 发布于 2012/03/09 14:14
阅读 1K+
收藏 0

本博客http://blog.csdn.net/livelylittlefish 贴 出作 者(三二一@小鱼)相关研究、学习内容所做的笔记,欢迎广大朋友指正!

 

1. 引子

 

实例 ( 4) 的基础上,能否将 container 写成模板类?

答案是肯定的。

 

2. 写成模板类应注意的问题

 

写成模板类,应该注意几个易出现的错误。

 

2.1 operator< 作为 MyIndex 类的成员函数 1

 

例如,将 operator< 作为 MyIndex 的成员函数,如下所示。

//define multiple index

typedef struct MyIndex

{

    int x;

    int y;

    int z;

 

    MyIndex (int ax = 0, int ay = 0, int az = 0): x(ax), y(ay), z(az){}

 

    bool operator<( const MyIndex& rhs )

    {

        if (x < rhs.x) return true;

        else if (x > rhs.x) return false;

        else if (y < rhs.y) return true;

        else if (y > rhs.y) return false;

        else if (z < rhs.z) return true;

        else if (z > rhs.z) return false;

        else return false;

    }

 

    void print(char* prompt) const

    {

        cout << "(" << x << ", " << y << ", " << z << ") - " << prompt << endl;

    }

}MyIndex ;

编译时会出现如下错误。

multiindexcontainer5.cpp:120:    instantiated from ‘void MyContainer::insert(Data_T*) [with MultiIndexContainer_T = boost::multi_index::multi_index_container, boost::multi_index::member, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::allocator >, Tag_T = MyIndexTag, Data_T = MyTest, Index_T = MyIndex]’

multiindexcontainer5.cpp:173:    instantiated from here

/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_function.h:227: error: passing ‘const MyIndex’ as ‘this’ argument of ‘bool MyIndex::operator<(const MyIndex&)’ discards qualifiers

大致意思是说,不应该将 operator<(const MyIndex&) 函数的参数声明为 const 。如果将 const 去掉,还是会出现错误,如下。

 

2.2 operator< 作为 MyIndex 类的成员函数 2

//define multiple index

typedef struct MyIndex

{

    int x;

    int y;

    int z;

 

    MyIndex (int ax = 0, int ay = 0, int az = 0): x(ax), y(ay), z(az){}

 

    bool operator<( MyIndex& rhs )

    {

        if (x < rhs.x) return true;

        else if (x > rhs.x) return false;

        else if (y < rhs.y) return true;

        else if (y > rhs.y) return false;

        else if (z < rhs.z) return true;

        else if (z > rhs.z) return false;

        else return false;

    }

 

    void print(char* prompt) const

    {

        cout << "(" << x << ", " << y << ", " << z << ") - " << prompt << endl;

    }

}MyIndex ;

编译错误如下。

multiindexcontainer5.cpp:120:    instantiated from ‘void MyContainer::insert(Data_T*) [with MultiIndexContainer_T = boost::multi_index::multi_index_container, boost::multi_index::member, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::allocator >, Tag_T = MyIndexTag, Data_T = MyTest, Index_T = MyIndex]’

multiindexcontainer5.cpp:173:    instantiated from here

/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_function.h:227: error: no match for ‘operator<’ in ‘__x < __y’

multiindexcontainer5.cpp:24: note: candidates are: bool MyIndex::operator<(MyIndex&)

大致意思是说, stl_function.h 的第 227 行需要的是一个有两个参数的 operator< ,但 MyIndex 类没有,只有 bool MyIndex::operator<(MyIndex&)

 

由上可知,在编译的时候,编译器会自动将 /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_function.h:227 所在的函数加入该程序。

先看看 stl_function.h 227 行的程序,如下。

 

221

222

223

224

225

226

227

228

/// One of the @link s20_3_3_comparisons comparison functors@endlink.

template

struct less : public binary_function<_Tp, _Tp, bool>

{

     bool

    operator()(const _Tp& __x, const _Tp& __y) const

{ return __x < __y; }

};

 

因此,我们需要将 bool MyIndex::operator<(MyIndex&) 改为 bool MyIndex::operator<(MyIndex& , MyIndex&) 但是依然会出现错误,如下。

 

2.3 operator< 作为 MyIndex 类的成员函数 3

//define multiple index

typedef struct MyIndex

{

    int x;

    int y;

    int z;

 

    MyIndex(int ax = 0, int ay = 0, int az = 0): x(ax), y(ay), z(az){}

 

    bool operator<( MyIndex& lhs, MyIndex& rhs )   //( const MyIndex& lhs, const MyIndex& rhs )

    {

        if (lhs.x < rhs.x) return true;

        else if (lhs.x > rhs.x) return false;

        else if (lhs.y < rhs.y) return true;

        else if (lhs.y > rhs.y) return false;

        else if (lhs.z < rhs.z) return true;

        else if (lhs.z > rhs.z) return false;

        else return false;

    }

 

    void print(char* prompt) const

    {

        cout << "(" << x << ", " << y << ", " << z << ") - " << prompt << endl;

    }

}MyIndex;

编译错误如下。

multiindexcontainer5.cpp:120:    instantiated from ‘void MyContainer::insert(Data_T*) [with MultiIndexContainer_T = boost::multi_index::multi_index_container, boost::multi_index::member, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::allocator >, Tag_T = MyIndexTag, Data_T = MyTest, Index_T = MyIndex]’

multiindexcontainer5.cpp:173:    instantiated from here

/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_function.h:227: error: no match for ‘operator<’ in ‘__x < __y’

multiindexcontainer5.cpp:24: note: candidates are: bool MyIndex::operator<(MyIndex&, MyIndex&)

且加不加 const 都是这样的错误。

 

按照提示,我们先看看程序第 120 173 行是什么。

 

117

118

119

120

121

template <class MultiIndexContainer_T, class Tag_T, class Data_T, class Index_T>

void MyContainer::insert(Data_T* data)

{

    theContainer.insert(data);

}

 

170

171

172

173

174

175

176

177

178

void test1()

{

    MyTest *a = new MyTest(1,1,1,10,100);

    mycontainer.insert(a);

    MyTest *b = new MyTest(1,1,2,20,200);

    mycontainer.insert(b);

    MyTest *c = new MyTest(1,1,3,30,300);

    mycontainer.insert(c);

}

 

由此,不难看出,使用 boost::multi_index boost::multi_index_container ,将数据插入某个 container 时,会自动进行 index 间的比较,有 ordered_unique ordered_non_unique ,如,

indexed_by< ordered_unique < ... >,  member <...> > >

 

Ordered_unique 定义如下,在 ../boost/multi_index/ordered_index.hpp 文件中。

/* ordered_index specifiers */

 

template

struct ordered_unique

{

  typedef typename detail::ordered_index_args<

    Arg1,Arg2,Arg3>                                index_args;

  typedef typename index_args::tag_list_type::type tag_list_type;

  typedef typename index_args::key_from_value_type key_from_value_type;

  typedef typename index_args::compare_type        compare_type;

 

  template

  struct node_class

  {

    typedef detail::ordered_index_node type;

  };

 

  template

  struct index_class

  {

    typedef detail::ordered_index<

      key_from_value_type,compare_type,

      SuperMeta,tag_list_type,detail::ordered_unique_tag> type;

  };

};

那么,到底如何写 operator< 函数,才不会出现这样的错误?

 

3. 正确的写法—— operator< 只是一个普通函数

bool operator<(const MyIndex& lhs, const MyIndex& rhs)

{

    if (lhs.x < rhs.x) return true;

    else if (lhs.x > rhs.x) return false;

    else if (lhs.y < rhs.y) return true;

    else if (lhs.y > rhs.y) return false;

    else if (lhs.z < rhs.z) return true;

    else if (lhs.z > rhs.z) return false;

    else return false;

}

4. container 模板类

 

在此例中,我们进一步将 container 写成模板类,如下。

//a template class

template <class MultiIndexContainer_T, class Tag_T, class Data_T, class Index_T>

class MyContainer

{

    MultiIndexContainer_T theContainer;

 

public:

    void insert(Data_T * data);

    void find(const Index_T & index);

    void print();

    void free();

};

5. 代码及运行结果

 

multiindexcontainer5.cpp

/**
 * boost multi index container test
 * platform: win32, visual studio 2005/2010; Linux, gcc4.1.2
 */
#include <iostream>
#include "boost/multi_index_container.hpp"
#include "boost/multi_index/member.hpp"
#include "boost/multi_index/ordered_index.hpp"
using namespace std;
using namespace boost::multi_index;
using boost::multi_index_container;
//define multiple index
typedef struct MyIndex
{
    int x;
    int y;
    int z;
    MyIndex(int ax = 0, int ay = 0, int az = 0): x(ax), y(ay), z(az){}
    void print(char* prompt) const
    {
        cout << "(" << x << ", " << y << ", " << z << ") - " << prompt << endl;
    }
}MyIndex;
//define data to be indexed
typedef struct
{
    int a;
    int b;
}MyData;
//define object to be indexed
class MyTest
{
public:
    MyIndex myIndex;
    MyData  myData;
public:
    MyTest(int x, int y, int z, int a, int b)
    {
        myIndex.x = x;
        myIndex.y = y;
        myIndex.z = z;
        myData.a = a;
        myData.b = b;
    }
    ~MyTest()
    {
        print(", destructed");
    }
    void print(char* prompt = "") const
    {
        cout << "(" << myIndex.x << ", " << myIndex.y << ", " << myIndex.z << ") - ";
        cout << "(" << myData.a << ", " << myData.b << ")" << prompt << endl;
    }
private:
    MyTest(const MyTest&);
    MyTest& operator= (const MyTest&);
};
//define index tag, multi_index_container, and its type
struct MyIndexTag{};
typedef multi_index_container<
    MyTest*,
    indexed_by<
        ordered_unique<
            tag<MyIndexTag>,  member<MyTest, MyIndex, &MyTest::myIndex> > > 
>MyContainer_T;
typedef MyContainer_T::index<MyIndexTag>::type MyContainerIndex_T;
typedef MyContainer_T::index<MyIndexTag>::type::iterator MyContainerIterator_T;
typedef std::pair<MyContainerIterator_T, bool> MyContainerPair_T;

//a template class
template <class MultiIndexContainer_T, class Tag_T, class Data_T, class Index_T>
class MyContainer
{
    MultiIndexContainer_T theContainer;
public:
    void insert(Data_T* data);
    void find(const Index_T& index);
    void print();
    void free();
};
template <class MultiIndexContainer_T, class Tag_T, class Data_T, class Index_T>
void MyContainer<MultiIndexContainer_T, Tag_T, Data_T, Index_T>::insert(Data_T* data)
{
    theContainer.insert(data);
}
template <class MultiIndexContainer_T, class Tag_T, class Data_T, class Index_T>
void MyContainer<MultiIndexContainer_T, Tag_T, Data_T, Index_T>::find(const Index_T& index)
{
    const typename boost::multi_index::index<MultiIndexContainer_T, Tag_T>::type& indexSet = get<Tag_T>(theContainer);
    const typename boost::multi_index::index<MultiIndexContainer_T, Tag_T>::type::iterator iter = indexSet.find(index);
    if (indexSet.end() == iter)
    {
        index.print("not found");
        return;
    }
    (*iter)->print(", found");
}
template <class MultiIndexContainer_T, class Tag_T, class Data_T, class Index_T>
void MyContainer<MultiIndexContainer_T, Tag_T, Data_T, Index_T>::print()
{
    const typename boost::multi_index::index<MultiIndexContainer_T, Tag_T>::type& indexSet = get<Tag_T>(theContainer);
    typedef typename MultiIndexContainer_T::value_type value_type;
    std::copy(indexSet.begin(), indexSet.end(), std::ostream_iterator<value_type>(cout));
}
template <class MultiIndexContainer_T, class Tag_T, class Data_T, class Index_T>
void MyContainer<MultiIndexContainer_T, Tag_T, Data_T, Index_T>::free()
{
    typedef typename MultiIndexContainer_T::value_type value_type;
    while (!theContainer.empty())
    {
        typename MultiIndexContainer_T::iterator iter = theContainer.begin();
        if (NULL == (*iter))
        {
            theContainer.erase(iter);
            continue;
        }
        value_type pobj = *iter;
        theContainer.erase(iter);
        delete pobj;
    }
}
bool operator<(const MyIndex& lhs, const MyIndex& rhs)
{
    if (lhs.x < rhs.x) return true;
    else if (lhs.x > rhs.x) return false;
    else if (lhs.y < rhs.y) return true;
    else if (lhs.y > rhs.y) return false;
    else if (lhs.z < rhs.z) return true;
    else if (lhs.z > rhs.z) return false;
    else return false;
}
std::ostream& operator<<(std::ostream& os, const MyTest* mytest)
{
    mytest->print();
    return os;
}
//instantiate a instance for this template class
MyContainer<MyContainer_T, MyIndexTag, MyTest, MyIndex> mycontainer;
void test1()
{
    MyTest *a = new MyTest(1,1,1,10,100);
    mycontainer.insert(a);
    MyTest *b = new MyTest(1,1,2,20,200);
    mycontainer.insert(b);
    MyTest *c = new MyTest(1,1,3,30,300);
    mycontainer.insert(c);
}
void test2()
{
    MyTest *a = new MyTest(1,2,1,40,400);
    mycontainer.insert(a);
    MyTest *b = new MyTest(1,2,2,50,500);
    mycontainer.insert(b);
    MyTest *c = new MyTest(1,2,3,60,600);
    mycontainer.insert(c);
}
void test3()
{
    MyTest *a = new MyTest(1,3,1,70,700);
    mycontainer.insert(a);
    MyTest *b = new MyTest(1,3,2,80,800);
    mycontainer.insert(b);
    MyTest *c = new MyTest(1,3,3,90,900);
    mycontainer.insert(c);
}
void test4()
{
    MyTest *a = new MyTest(2,1,1,110,1000);
    mycontainer.insert(a);
    MyTest *b = new MyTest(2,1,2,220,2000);
    mycontainer.insert(b);
    MyTest *c = new MyTest(2,1,3,330,3000);
    mycontainer.insert(c);
}
void test5()
{
    MyTest *a = new MyTest(2,2,1,440,4000);
    mycontainer.insert(a);
    MyTest *b = new MyTest(2,2,2,550,5000);
    mycontainer.insert(b);
    MyTest *c = new MyTest(2,2,3,660,6000);
    mycontainer.insert(c);
}
void test6()
{
    MyTest *a = new MyTest(2,3,1,770,7000);
    mycontainer.insert(a);
    MyTest *b = new MyTest(2,3,2,880,8000);
    mycontainer.insert(b);
    MyTest *c = new MyTest(2,3,3,990,9000);
    mycontainer.insert(c);
}
void test_find()
{
    mycontainer.find(MyIndex(1,1,1));
    mycontainer.find(MyIndex(1,1,2));
    mycontainer.find(MyIndex(1,1,3));
    mycontainer.find(MyIndex(1,2,1));
    mycontainer.find(MyIndex(1,2,2));
    mycontainer.find(MyIndex(1,2,3));
    mycontainer.find(MyIndex(1,3,1));
    mycontainer.find(MyIndex(1,3,2));
    mycontainer.find(MyIndex(1,3,3));
    mycontainer.find(MyIndex(2,1,1));
    mycontainer.find(MyIndex(2,1,2));
    mycontainer.find(MyIndex(2,1,3));
    mycontainer.find(MyIndex(2,2,1));
    mycontainer.find(MyIndex(2,2,2));
    mycontainer.find(MyIndex(2,2,3));
    mycontainer.find(MyIndex(2,3,1));
    mycontainer.find(MyIndex(2,3,2));
    mycontainer.find(MyIndex(2,3,3));
}
int main()
{
    test2();
    test4();
    test6();
    test1();
    test3();
    test5();
    mycontainer.print();
    cout<<endl;
    test_find();
    cout<<endl;
    mycontainer.free();
    return 0;
}

运行结果如下:

(1, 1, 1) - (10, 100)

(1, 1, 2) - (20, 200)

(1, 1, 3) - (30, 300)

(1, 2, 1) - (40, 400)

(1, 2, 2) - (50, 500)

(1, 2, 3) - (60, 600)

(1, 3, 1) - (70, 700)

(1, 3, 2) - (80, 800)

(1, 3, 3) - (90, 900)

(2, 1, 1) - (110, 1000)

(2, 1, 2) - (220, 2000)

(2, 1, 3) - (330, 3000)

(2, 2, 1) - (440, 4000)

(2, 2, 2) - (550, 5000)

(2, 2, 3) - (660, 6000)

(2, 3, 1) - (770, 7000)

(2, 3, 2) - (880, 8000)

(2, 3, 3) - (990, 9000)

 

(1, 1, 1) - (10, 100), found

(1, 1, 2) - (20, 200), found

(1, 1, 3) - (30, 300), found

(1, 2, 1) - (40, 400), found

(1, 2, 2) - (50, 500), found

(1, 2, 3) - (60, 600), found

(1, 3, 1) - (70, 700), found

(1, 3, 2) - (80, 800), found

(1, 3, 3) - (90, 900), found

(2, 1, 1) - (110, 1000), found

(2, 1, 2) - (220, 2000), found

(2, 1, 3) - (330, 3000), found

(2, 2, 1) - (440, 4000), found

(2, 2, 2) - (550, 5000), found

(2, 2, 3) - (660, 6000), found

(2, 3, 1) - (770, 7000), found

(2, 3, 2) - (880, 8000), found

(2, 3, 3) - (990, 9000), found

 

(1, 1, 1) - (10, 100), destructed

(1, 1, 2) - (20, 200), destructed

(1, 1, 3) - (30, 300), destructed

(1, 2, 1) - (40, 400), destructed

(1, 2, 2) - (50, 500), destructed

(1, 2, 3) - (60, 600), destructed

(1, 3, 1) - (70, 700), destructed

(1, 3, 2) - (80, 800), destructed

(1, 3, 3) - (90, 900), destructed

(2, 1, 1) - (110, 1000), destructed

(2, 1, 2) - (220, 2000), destructed

(2, 1, 3) - (330, 3000), destructed

(2, 2, 1) - (440, 4000), destructed

(2, 2, 2) - (550, 5000), destructed

(2, 2, 3) - (660, 6000), destructed

(2, 3, 1) - (770, 7000), destructed

(2, 3, 2) - (880, 8000), destructed

(2, 3, 3) - (990, 9000), destructed



Technorati 标签: , ,


原文链接:http://blog.csdn.net/livelylittlefish/article/details/6098472
加载中
返回顶部
顶部