3

stl copy() を使用してキーと値のペアをマップに出力しようとしています。コードは次のとおりです。

#include <iterator>
#include <iostream>
#include <algorithm>
#include <map>

using namespace std;
//compile error if I comment out "namespace std"
namespace std {    
template<typename F, typename S> 
ostream& operator<<(ostream& os, const pair<F,S>& p) {
  return os << p.first << "\t" << p.second << endl;
}
}

int main() {
  map<int, int> m;
  fill_n(inserter(m, m.begin()), 10, make_pair(90,120));
  copy(m.begin(), m.end(), ostream_iterator<pair<int,int> >(cout,"\n"));
} 

operator<< をオーバーロードしようとしています。問題は、オーバーロードされた operator<< の定義を で囲まない限り、コードがコンパイルされないことnamespace stdです。C++の名前検索の仕組みによるものだと思うのですが、いまだに理解に苦しむところがあります。次のように非テンプレート バージョンを定義しても、

ostream& operator<<(ostream& os, const pair<int,int>& p) {
    return os << p.first << "\t" << p.second << endl;
}

それでもコンパイルされません。誰でも理由を説明できますか?

4

1 に答える 1

2

問題は、引数依存の名前検索(ADL)にあります。コンパイラは、とがその名前空間にあるため、 operator<<inの実装を検索しています。正しい名前空間からに転送するラッパーを作成する必要があります。namespace stdostreampairoperator<<

template<class T>
struct ostreamer {
  ostreamer(const T& value) : reference(value) {}
  const T& reference;
  friend ostream& operator<<(ostream& stream, const ostreamer& value) {
    return stream << value.reference;
  }
};

次に、ostream_iterator<ostreamer<pair<const int, int>>>の代わりに使用しostream_iterator<pair<int, int>>ます。値ではなく参照によって保存されるため、からへostreamerの暗黙の変換に依存することはできなくなります。値で保存するように変更することもできますが、そのままではオーバーヘッドがないので、とにかく明示的にする方が良いと思います。pair<const int, int>pair<int, int>ostreamer

于 2013-02-19T02:47:32.030 に答える