使用copy算法输出map中的内容

来源:互联网 发布:java颜色代码 编辑:程序博客网 时间:2024/05/22 22:38

   在C++中,我们常用STL中的copy算法输出序列容器中的元素到输出流。例如我们有一个vector<int>容器,现在我们要将它的内容输出到cout。根据效率考虑,我们不应该使用loop语句实现。我们可以使用copy算法,用习惯i啊棉的语句:

   copy(vec.begin(),vec.end().ostream_iterator<int>(cout," "));
这样就可以使用非常简洁的一行代码实现我们的意图。但是如果我们现在想要输出的容器是关联容器呢,比如说map,如果直接将上面代码中的vector<int>换成map<string,int>的话,是不能实现我们的要求的。因为在copy函数中,会调用操作符<<函数,在pair结构的定义中,没有定义对这个操作符的重载。因此需要我们自己实现。

     最初我实现的代码如下所示

 template<typename S, typename T> ostream& operator<<(ostream& os, const pair<S,T>& p) {    os << p.first << " " << p.second;    return os; }int main(){    map<string, int> stringIntMap;    stringIntMap.insert(make_pair("hello",1));    stringIntMap.insert(make_pair("world",2));    stringIntMap.insert(make_pair("2011",3));    for (map<string,int>::iterator it = stringIntMap.begin();it != stringIntMap.end();it++)        cout << it->first << " " << it->second << endl;    cout << "post: \n";    copy(stringIntMap.begin(),stringIntMap.end(),ostream_iterator< pair<string,int> >(cout,"\n"));    return 0;}
但是上面的代码无法编译通过,应为在调用copy函数时,copy函数会调用pair对应的<<操作符。pair定义在std命名空间中,但是在std中,没有对pair对应的《进行重载。所以无法编译通过。

一种改进方法就是把新定义的模版函数添加到std命名空间中,即将模版函数定义修改为:

namespace std{template<typename S, typename T>ostream& operator<<(ostream& os, const pair<S,T>& p){os << p.first << " " << p.second;return os;}}
这样就可以编译通过。但是一般来说我们不应该修改std中的内容。另一中改进就是对pair进行封装,代码如下所示:
#include <iostream>#include <vector>#include <iterator>#include <algorithm>#include <map>#include <set>#include <string>#include <cstring>using namespace std;template<typename M,typename U>struct newPair{M first;U second;newPair():first(M()),second(U()){}template<typename T1,typename T2>newPair(const pair<T1,T2>& p):first(p.first),second(p.second){}};template<typename M,typename U>ostream& operator<<(ostream& os, const newPair<M,U>& p){os << p.first << " " << p.second;return os;}int main(){map<string, int> stringIntMap;stringIntMap.insert(make_pair("hello",1));stringIntMap.insert(make_pair("world",2));stringIntMap.insert(make_pair("2011",3));for (map<string,int>::iterator it = stringIntMap.begin();it != stringIntMap.end();it++)cout << it->first << " " << it->second << endl;cout << "post: \n";copy(stringIntMap.begin(),stringIntMap.end(),ostream_iterator< newPair<string,int> >(cout,"\n"));return 0;}
这样编译器就会在newPair定义所在的文件查找对<<操作符的重载。

这样也就实现了我们的意图。当然其实我觉得不一定有必要这样操作,使用一个循环就可以了,但是从这个例子中我们知道编译器查找相关的函数时,只在定义相关类的文件中查找

当然我们还可以使用for_each函数实现,但是这个函数明显没有copy直观。