Young's Blog

包子铺

C++中使用copy和ostream_iterator来输出map的内容

对于copy配合iterator来输出一些容器的便利性是非常喜欢的,但是copy在处理map容器的时候,很容易导致编译出错,问题代码如下:
 1 ostream& operator << (ostream& outconst pair<const int,int>& value)
 2 {
 3     out<<"("<<value.first<<","<<value.second<<")";
 4     return out;
 5 }
 6 int main()
 7 {
 8     map<intint> imap;
 9     for(int i=0;i<10++i)
10     {
11         imap.insert( map<int,int>::value_type(i, i*10) );
12     }
13     copy(imap.begin(), imap.end(), ostream_iterator<pair<const intint> >(cout,","));
14     cout<<endl;
15 }

这个问题的起因:在遇到key和value为内置类型或std::类型的时候,编译器无法找到用户自定义的operator <<操作符。在处理上述代码时,编译只会在std里查找pair的operator <<定义。

解决的办法:
1.使用非内置类型和非std::类型。
2.使用transform函数取代copy函数。

对于第一种解决方法,我们只用重封装一下就可以:
 1 struct MyType
 2 {
 3     int value;
 4 };
 5 
 6 ostream& operator << (ostream& outconst pair<const int, MyType>& value)
 7 {
 8     out<<"("<<value.first<<","<<value.second.value<<")";
 9     return out;
10 }
11 
12 int main()
13 {
14     map<int, MyType> imap;
15     for(int i=0;i<10++i)
16     {
17         MyType tmp = { i*10 };
18         imap.insert( map<int, MyType>::value_type(i, tmp) );
19     }
20 
21     copy(imap.begin(), imap.end(), ostream_iterator<pair<const int, MyType> >(cout,","));
22     cout<<endl;
23 }

对于第二种方法,则必需要写一个toString的函数来把pair的数据处理一下:
 1 ostream& operator << (ostream& outconst string& str)
 2 {
 3     return out<<str;
 4 }
 5 
 6 string toString(const pair<const intint>& value)
 7 {
 8     ostringstream ost;
 9     ost<<"("<<value.first<<","<<value.second<<")";
10     return ost.str();
11 }
12 
13 int main()
14 {
15     map<intint> imap;
16     for(int i=0;i<10++i)
17     {
18         imap.insert( map<int,int>::value_type(i, i*10) );
19     }
20 
21     transform(imap.begin(), imap.end(), ostream_iterator<string>(cout, " "), toString);
22     cout<<endl;
23 }

除此之外,如果我们采用了第一种方法,自己定义了一个结构体,作为map的value来作用,希望通过copy函数能直接输出相应的内容。那么我们一般会先定义一个结构体的operator <<操作:
 1 namespace TEST_NS{
 2 
 3     struct Info{
 4         unsigned int Value;
 5     };  
 6 
 7     //第一个operator <<操作,这里是处理Info的
 8     ostream& operator << (ostream& Out, const Info& Obj){   
 9         Out<<"NAME:"<<Obj.Value<<endl;
10         return Out;
11     }   
12 }

然后在外面使用了map来对Info数据进行存储,那么我们会再定义一个operator<<用来处理map的内容:
1 using namespace TEST_NS;
2 
3 //第二个operator <<操作,这里是处理pair<const unsigned int, Info>的
4 ostream& operator<<(ostream& Out, const pair<const unsigned int, Info>& Obj){
5     Out<<Obj.second<<endl;                                 
6     return Out;
7 }
8 

然后我们的main函数就这样子处理:
 1 int main()
 2 {
 3     map<unsigned int, Info> MyData;
 4 
 5     for(unsigned int i = 1; i<10++i ){
 6         Info info;
 7         info.Value = i;
 8         MyData.insert( map<unsigned int, Info>::value_type( i, info ) );
 9     }   
10 
11     copy( MyData.begin(), MyData.end(), ostream_iterator< pair<const unsigned int, Info> >(cout, ",") );
12 }
13 


上面的代码看起来一点问题都没有,但是会依然导致出错。原因在于编译器找不到Info的operator <<函数。解决方法为,把第二个operator <<放到第一个operator <<相同的名字空间里去。


posted on 2012-11-18 23:32 Young 阅读(5482) 评论(0)  编辑 收藏 引用 所属分类: STL


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理