Possible bug in ostream_iterator

Daniel Krügler daniel.kruegler@gmail.com
Wed Dec 11 19:50:00 GMT 2013


2013/12/11 John Schmerge <jbschmerge@gmail.com>:
>   I ran into a curiosity that is causing an error for me with both gcc
> 4.7.x and 4.8.1 (I haven't tried with 4.8.2 yet):
>
> <example_code>
>
> #include <iostream>
> #include <iterator>
> #include <string>
> #include <utility>
>
> using EnvPair = std::pair<const std::string, std::string>;
>
> // the function signature here is adapted from the output operator
> from std::complex...
> // most likely the same issues would exist with that class
> template <class CharT, class Traits>
> std::basic_ostream<CharT, Traits> &
> operator << (std::basic_ostream<CharT, Traits> & out, const EnvPair & ep)
> {
>     out << std::get<0>(ep) << "=" << std::get<1>(ep);
>     return out;
> }

I'd like to remark here that you added an operator in the global
namespace for types that are defined in namespace std.

> int main(int argc, char ** argv)
> {
>     EnvPair ep{ "foo", "bar" };
>
>     // No problem
>     std::cout << ep << '\n' << std::string(70, '-') << std::endl;
>
>     std::ostream_iterator<EnvPair> out_iter(std::cout, "\n");
>
> #ifdef BROKEN
>     out_iter = ep;
> #endif
>
>     return 0;
> }
> </example_code>
>
> What i get when the output iterator assignment is enabled is the
> following error:

The error is expected: The ostream_iterator implementation is defined
in a context where the expression of the form "a << b" is evaluated
considers argument-dependent lookup (with the definition of
operator=). The effect is that only associated namespaces are
considered (Slightly simplified: Those where the participating
operators belong to), and both belong to namespace std, so only
namespace std will be considered to find such a function. Every
conforming implementation should reject this code. Don't put functions
that are supposed to be found by ADL in different namespaces than all
operands. Since you are not allowed to add overloads to namespace std,
the usual idiom here is to define a proxy template in some namespace
of your choice that wraps the interested type and to add an operator<<
that takes this proxy in the same namespace. This will have the
intended effect that ADL will find the operator even for wrapped
types.

- Daniel



More information about the Libstdc++ mailing list