bimap是boost中很重要的一个容器 ,可以进行双向的查找和替换 ,这样弥补了如果map和multimap需要找到data所对应的键值 。循环遍历元素 ,才能找到相应的键值 ,再删除 ,最后替换的不足 。
但是boost的模板源编程又有着先天的缺点 ,就是编译错误不容易找到 ,编译时间有点长。但是如果长期使用boost ,知道常见的错误 ,这个缺点还是可以慢慢克服的;虽然编译时间是有点长,但是比起自己一行一行自己写 ,还是说的过去的 。
下面是需要的一些头 ,如果只是简单使用bimap,仅引入#include就可以了
[html] view plaincopyprint?
#include<iostream>
#include<map>
#include<boost/foreach.hpp>
#include<boost/typeof/typeof.hpp>
#include<boost/bimap.hpp>
#include<boost/bimap/set_of.hpp>
#include<boost/bimap/vector_of.hpp>
//#include<boost/bimap/tags/tagged.hpp>
usingnamespaceboost::bimaps;
usingnamespaceboost;
usingnamespacestd;
#include
<iostream>
#include
<map>
#include <boost/foreach.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/bimap.hpp>
#include <boost/bimap/set_of.hpp>
#include <boost/bimap/vector_of.hpp>
//#include <boost/bimap/tags/tagged.hpp>
usingnamespace boost::bimaps;
usingnamespace boost;
usingnamespace std;
首先写出一个打印bimap的工具函数,这个函数不仅可以打印bimap也可以打印map和multimap 。
这里用到了boost很常用的BOOST_AUTO和BOOST_FOREACH 。个人比较倾向于我写的第一个实现 。
如果在程序灵活的使用boost的一些宏是可以很多的代码的 。
这里BOOST_FOREACH要比BOOST_AUTO要简明一些 。但是试想如果不能用这两个的话 ,for循环的第一个参数应该写多长啊 。
[html] view plaincopyprint?
//打印所有元素
template<classT>
voidprint_map(T&m)
{
//方式一比较喜欢用的方式
BOOST_FOREACH(T::value_typev,m)
{
cout<<v.first<<""<<v.second<<endl;
}
//方式二
//for(BOOST_AUTO(pos,m.begin());pos!=m.end();++pos)
//{
//cout<<pos->first<<"--------"<<pos->second<<endl;
//}
}
//打印所有元素
template
<classT>
voidprint_map(T &m)
{
//方式一 比较喜欢用的方式
BOOST_FOREACH(T::value_type v,m)
{
cout<<v.first<<" "<<v.second<<endl;
}
//方式二
// for (BOOST_AUTO(pos,m.begin());pos!=m.end();++pos)
// {
// cout<
<pos->first<<"--------"<
<pos->second<<endl;
// }
}
切记 简单bimap key/value 从两个个方向看必须都是唯一 ,虽然这个规则可以在后面改变
[html] view plaincopyprint?
typedefbimap<int,std::string>bm_t;
typedefbimap<int,std::string> bm_t;
如果插入的值不唯一,将会显示第一次插入的结果 。
下面是左值重复插入测试
[html] view plaincopyprint?
intmain()
{
std::map<int,int>test;
//先创建
test[1]=2;
//再修改
test[1]=4;
cout<<test[1]<<endl;//结果:4
//bimap左值重复测试
bm_tcol;
col.left.insert(make_pair(5,"hello"));
//虽然无效 ,但是可以插入
col.left.insert(make_pair(5,"world"));
//测试显示的是第一次插入的值
BOOST_AUTO(iter,col.left.find(5));
cout<<"lefteuql:"<<iter->second<<endl;//结果:hello
//bimap右值重复测试
col.right.insert(make_pair("hello",10));
BOOST_AUTO(iter2,col.right.find("hello"));
//对于右值查询 ,常量输出的方向应该相反 ,原first变seoond
//测试同样显示的是第一次插入的值
cout<<"rightequal:"<<iter2->second<<endl;//结果:5
intmain()
{
std::map<int,int> test;
//先创建
test[1] = 2;
//再修改
test[1] = 4;
cout<<test[1]<<endl; //结果:4
//bimap左值重复测试
bm_t col;
col.left.insert(make_pair(5,"hello"));
//虽然无效 ,但是可以插入
col.left.insert(make_pair(5,"world"));
//测试显示的是第一次插入的值
BOOST_AUTO(iter,col.left.find(5));
cout<<"left euql:"<
<iter->second<<endl; //结果:hello
//bimap右值重复测试
col.right.insert(make_pair("hello",10));
BOOST_AUTO(iter2,col.right.find("hello"));
//对于右值查询 ,常量输出的方向应该相反 ,原first变seoond
//测试同样显示的是第一次插入的值
cout<<"right equal:"<
<iter2->second<<endl;//结果:5
不能使用map的方式要访问简单的bimap ,否则会造成
编译错误 ,提示 error C2664: ‘boost::mpl::assertion_failed’ : cannot convert parameter 1 from ‘boost::mpl::failed
对于模版源编程 ,熟悉一些错误对程序的纠错是非常有好处的
虽然不能像关联数组一样使用operator[],但这个不是绝对的 。
可以使用来使用operator[]
[html] view plaincopyprint?
cout<<col.left[5]<<endl;
cout<<col.left[5]<<endl;
下面是右值重复插入测试
[html] view plaincopyprint?
typedefbm_t::value_typeval;
//不使用左右视图,使用value_type插入元素
col.insert(val(50,"test_value_type"));
typedefbm_t::left_value_typeleft_val;
//使用left_value_type插入元素
//同理right_value_type插入元素
col.left.insert(left_val(100,"left_value_type"));
//传入一个左视图的结果集
print_map(col.left);
typedefbm_t::value_type val;
//不使用左右视图 ,使用 value_type 插入元素
col.insert(val(50,"test_value_type"));
typedefbm_t::left_value_type left_val;
//使用 left_value_type 插入元素
//同理 right_value_type 插入元素
col.left.insert(left_val(100,"left_value_type"));
//传入一个左视图的结果集
print_map(col.left);
使用bimap库的一些类和方法可以使用可以使用operator[] ,而且可以不唯一key/value的bimap,但必须保证左视图为有序 ,右视图为随意访问类型。
[html] view plaincopyprint?
bimap<boost::bimaps::set_of<int>,boost::bimaps::vector_of<std::string>>bm_multi;
bm_multi.left.insert(make_pair(1,"111"));
bm_multi.left[2]="222";
bm_multi.left[300]="bimap";
cout<<"useoperator:"<<bm_multi.left[300]<<endl;
print_map(bm_multi.left);
//输出
//1111
//2222
//300bimap
bimap<boost::bimaps::set_of
<int>,boost::bimaps::vector_of<std::string> > bm_multi;
bm_multi.left.insert(make_pair(1,"111"));
bm_multi.left[2] = "222";
bm_multi.left[300] = "bimap";
cout<<"use operator: "<<bm_multi.left[300]<<endl;
print_map(bm_multi.left);
//输出
//1 111
//2 222
//300 bimap
对于常见的访问类型 ,见下:
set_of , multiset_of , unordered_set_of ,unordered_multiset_of : 可以做键值索引
list_of ,vector_of ,unconstrained_set_of :不能用作键值索引
关于这部分的具体内容可以参考《Boost程序库完全开发指南》P264
关于 boost bimap 的tagged,使用boost tagged 给左右视图增加标签 这个功能在vs下不太稳定 ,但也可能是本人编译器的问题
[html] view plaincopyprint?
bimap<tagged<int,structid>,tagged<std::string,structname>>bm_tag_test;
bm_tag_test.by<id>{}.insert(make_pair(1,"hello"));
bm_tag_test.by<id>{}.insert(make_pair(2,"world"));
bm_tag_test.by<name>{}.insert(make_pair("test",3));
print_map(bm_tag_test.by<name>());
bimap<tagged<int,structid> ,tagged<std::string ,structname> > bm_tag_test;
bm_tag_test.by
<id>{}.insert(make_pair(1,"hello"));
bm_tag_test.by
<id>{}.insert(make_pair(2,"world"));
bm_tag_test.by
<name>{}.insert(make_pair("test",3));
print_map(bm_tag_test.by
<name>());
}
关于bimap的投射和替换 ,查找 ,修改功能 ,下次再给出详细说明 。
声明:本站所有文章 ,如无特殊说明或标注 ,均为本站原创发布 。任何个人或组织 ,在未征得本站同意时 ,禁止复制 、盗用 、采集、发布本站内容到任何网站 、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益 ,可联系我们进行处理 。