Я пытаюсь использовать 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"));
}
Я пытаюсь перегрузить оператора<<, Проблема в том, что код не будет компилироваться, если я не окружу определение перегруженного оператора<< с namespace std
, Я думаю, что это связано с механизмом поиска имен в C ++, который я до сих пор не понимаю. Даже если я определю не шаблонную версию следующим образом:
ostream& operator<<(ostream& os, const pair<int,int>& p) {
return os << p.first << "\t" << p.second << endl;
}
Это все еще не скомпилируется. Кто-нибудь может объяснить почему?
Ваша проблема с поиск имени в зависимости от аргумента (ADL). Компилятор ищет реализацию operator<<
в namespace std
, Как оба ostream
а также pair
находятся в этом пространстве имен. Вы должны сделать обертку, которая пересылает operator<<
из правильного пространства имен:
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
хранить по значению, но, как оно есть, оно не имеет накладных расходов, и я думаю, что в любом случае лучше быть явным.
Других решений пока нет …