Matthew Reddington
Matthew Reddington

Reputation: 1409

ADL can't locate stream operator with appropriate qualifiers for a user defined type

I'm compiling an x64 service on Microsoft Windows 7 with Visual Studio 2010, using a Boost variant something like:

namespace my_ns
{
    typedef struct {} empty_t;
    typedef std::pair<size_t, std::shared_ptr<char>> string_t;
    typedef boost::variant<empty_t, double, long, string_t> variant_t;
    typedef std::map<unsigned short, variant_t> variant_map_t;
}

The day I get rid of that string_t and replace it with an std::string is the day I buy my boss and the team donuts. But that's not why we're here...

The Boost variant supports the stream operators for its containted types provided the type has an overload. So I have:

namespace my_ns
{
    std::ostream &operator<<(std::ostream &, const empty_t &);
    std::ostream &operator<<(std::ostream &, const string_t &);
}

And yet, I am plagued with the error message:

error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'const T3' (or there is no acceptable conversion)

T3 refers to the string_t.

The offending code generating the error exists in the following context. It's verbose so you, the reader, have relevant context information:

namespace my_ns
{
    void Widget::public_method(std::ostringstream &os) const
    {
        //variant_map_t Widget::the_map; // Private Widget member.

        // This here is a C++11 lambda in a standard loop algorithm, if you didn't recognize the syntax.
        std::for_each(the_map.begin(), the_map.end() [&os](variant_map_t::value_type value)
        {
            os << value.first << '=' << value.second << ' ';
        });
    }
}

I have attempted removing the right hand qualifiers and reference, thinking passing a copy by value would knock off the qualifiers (probably not so brilliant in light of a shared pointer), and I've tried moving the declarations from the namespace to global scope, hoping ADL would pick it up for some reason (I get ADL, conceptually, but there's still just that little bit of black magic to it for me).

I don't know what else to do. What is the nature of this bug beyond the compiler is unable to locate an insertion operator with a const qualified rhs? How can that be, when it's right there? And what is the resolution?

Upvotes: 2

Views: 374

Answers (1)

Bo Persson
Bo Persson

Reputation: 92291

It doesn't help that you add a typedef to your namespace, std::pair and std::ostream are still part of the std namespace. So the compiler will look there for the << operator, and not in your namespace.

Upvotes: 1

Related Questions