Answering this SO question (it is better to read this "duplicate" ), I came up with a solution to the dependent resolution of operator names:
[temp.dep.res] / 1:
When resolving dependent names, names from the following sources are taken into account:
- Ads that are visible at the template definition point.
- Declarations from namespaces associated with function argument types both from the creation context (14.6.4.1) and from the definition context.
#include <iostream> #include <utility> // this operator should be called from inside `istream_iterator` std::istream& operator>>(std::istream& s, std::pair<int,int>& p) { s >> p.first >> p.second; return s; } // include definition of `istream_iterator` only after declaring the operator // -> temp.dep.res/1 bullet 1 applies?? #include <iterator> #include <map> #include <fstream> int main() { std::ifstream in("file.in"); std::map<int, int> pp; pp.insert( std::istream_iterator<std::pair<int, int>>{in}, std::istream_iterator<std::pair<int, int>>{} ); }
But clang ++ 3.2 and g ++ 4.8 did not find this operator (name resolution).
Does the <iterator> definition istream_iterator "template definition point" istream_iterator ?
Edit: since Andy Pull points out that this has nothing to do with the standard library, but rather with a name lookup (you can prove by imitating the standard library with a few operator>> at least one in the istream fake istream ).
Edit2: Workaround using [basic.lookup.argdep] / 2 bullet 2
#include <iostream> #include <utility> // can include <iterator> already here, // as the definition of a class template member function // is only instantiated when the function is called (or explicit instantiation) // (make sure there are no relevant instantiations before the definition // of the operator>> below) #include <iterator> struct my_int { int m; my_int() : m() {} my_int(int p) : m(p) {} operator int() const { return m; } }; // this operator should be called from inside `istream_iterator` std::istream& operator>>(std::istream& s, std::pair<my_int,my_int>& p) { s >> p.first.m >> p.second.m; return s; } #include <map> #include <fstream> int main() { std::ifstream in("file.in"); std::map<int, int> pp; pp.insert( std::istream_iterator<std::pair<my_int, my_int>>{in}, std::istream_iterator<std::pair<my_int, my_int>>{} ); }
Of course, you can also use your own pair type if the workaround represents a related class in the user operator>> namespace.