There are two problems with this line (outside of the fact that it makes no sense):
std::ostream_iterator{std::cout} = p;
First, std::ostream_iterator
is a class template, not a class. So you probably meant:
std::ostream_iterator<Point>{std::cout} = p;
Now, how does ostream_iterator::operator=
actually work? It does rely on operator<<
, but in the context of the definition of that member function of that class template. So the overloads that it will find are those in the scope of ostream_iterator
's operator=
(which yours is not) and those that can be found in the associated namespaces of the arguments (which yours is not again). That's why lookup fails.
If you simply move your operator<<
into namespace temp
:
namespace temp {
std::ostream& operator<<(std::ostream& s, Point p) {
return s << p.x;
}
}
Or as a non-member friend:
namespace temp {
struct Point {
int x;
friend std::ostream& operator<<(std::ostream& s, Point p) { ... }
};
}
Then argument-dependent lookup succeeds, and this works:
std::ostream_iterator<Point>{std::cout} = p;
That said, don't write that code. Use the normal std::cout << p
.
Here's another example of the same phenomenon that might be easier to understand. Let's say we have some function template that just calls another function on its argument:
template <class T>
void call_f(T val) {
f(val);
}
f
will be found by lookup from the point of definition of call_f
or via argument-dependent lookup on val
. So if we later do something like:
namespace N {
struct X { };
}
void f(N::X ) { }
int main() {
f(N::X{}); // ok
call_f(N::X{}); // error: can't find 'f'
}
That line errors because from the point of definition of call_f
, there is no function f()
(at all) and there is no function f
in namespace N
either. But if we move f
into that namespace, both versions work fine:
template <class T>
void call_f(T val) { f(val); }
namespace N {
struct X { };
void f(X ) { }
}
int main() {
f(N::X{}); // ok
call_f(N::X{}); // now ok too, ADL finds N::f
}