On May 9, 4:37 pm, mrstephengross <mrstephengr...@hotmail.com> wrote:
> Hi folks. I've got a weird situation--gcc doesn't like the folllowing
> code snippet, but I don't know if it's correct or not. Here's the
> situation:
> In the global namespace, I've got a operator<< declared that will send
> a vector<T> to a std:
stream.
Note that you cannot do this reliably. In order for the
compiler to reliably find the operator, including in template
code where it occurs in a dependent context, it must be able to
find it using ADL. Which means that the operator must be in std
(or the namespace in which T is defined---built-in types are in
no namespace, however). And you cannot, legally, add things
like this to std.
> In the "outer" namespace, I've got a operator<< declared that will
> send a Thing<T> to a std:
stream.
> In the "outer" namespace, I've got a function "foo" that tries to send
> a vector<T> to a std:
stream.
> When I try to compile it, gcc complains that there's no match for
> operator<< in the foo function's definition.
> Is this correct? Why is gcc not seeing the global namespace
> operator<< ?
> === test.cpp ===
> #include <iostream>
> #include <vector>
> template<typename T> std:
stream & operator<< (std:
stream & o,
> const std::vector<T> & v);
> namespace outer {
> template<class T> class Thing { };
> template<typename T> std:
stream & operator<< (std:
stream & o,
> const Thing<T> & t);
> void foo() { std::vector<double> v; std::cout << v; }
> }
> int main()
> {
>
> }
> === EOF ===
G++ is correct. Unqualified lookup stops when it finds the
name, here, in outer, and doesn't look further. That exposes
the operator<< in outer, and no other operator<<. ADL kicks in,
and causes lookup in the namespaces related to the arguments:
here, std, so the operator<< in std are also added to the
overload set. There's nothing to cause the compiler to look in
the global namespace, however. The built-in types are defined
in no namespace (and can't have any effect on ADL), and not in
the global namespace.
Faced with this problem, there are two answers, depending on
context:
-- In production code: don't do this. You never, never want to
overload << on something like std::vector<double> in
production code. It will introduce subtle coupling, and
will cause problems in the long run. When you need to
output a vector, either write function to do it, or use the
decorator pattern to call operator<< on one of your types.
-- For quick tests, or playing around: it's formally undefined
behavior to define this operator in namespace std, but in
practice, it won't cause any problems, so just go ahead and
do it

.
Note that both of the above solutions depend on ADL, and so will
also work from within a template.
--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34