ostream operator<< resolution fails when used from different namespaces

72 views Asked by At

I made overload for ostream operator<< for std::vector in namespace printable. As far as I understand, ADL will not see this overload implicitly, because std::vector is not a member of printable, so we must use printable namespace in calling code to see this overload.

In other namespace, my::fails i define another overload for my class foo. After that code breaks and doesn't compile.

In namespace my::suddenly_works I'm not using whole namespace printable, only operator<<, and... everything is ok. Why? What's the difference.

After that, in my::works I don't define any additoinal overloads and simply use namespace printable, using overloaded operator. Everything is fine, as expected.

So, the question is: how to correctly overload ostream operator<< in namespace for types not defined in this namespace, and how to use these overloads in another namespaces on calling side.

Also, as a side question, what's the difference between using namespace printable and using printable::operator<< in given example?

Here is the code (godbolt link):

#include <iostream>
#include <vector>

namespace printable
{
    template <typename T>
    inline auto operator<<(std::ostream& os, std::vector<T> const & v) -> std::ostream &
    {
        os << '[';
        for (auto it = v.cbegin(); it != v.cend() - 1; ++it)
        {
            os << *it << ", ";
        }
        os << v.back() << ']';

        return os;
    }
}

namespace my::fails
{

    struct foo {};

    inline auto operator<<(std::ostream& os, foo const & f) -> std::ostream &
    {
        std::vector v{1, 2, 3, 4, 5};
        std::cout << v << '\n';
        return os;
    }

    using namespace printable;
    void print_vec()
    {
        std::vector v{1, 2, 3, 4, 5};
        std::cout << v << '\n';
    }
}

namespace my::suddenly_works
{
    using printable::operator<<;

    struct foo {};

    inline auto operator<<(std::ostream& os, foo const & f) -> std::ostream &
    {
        std::vector v{1, 2, 3, 4, 5};
        std::cout << v << '\n';
        return os;
    }

    void print_vec()
    {
        std::vector v{1, 2, 3, 4, 5};
        std::cout << v << '\n';
    }
}

namespace my::works
{
    using namespace printable;

    void print_vec()
    {
        std::vector v{1, 2, 3, 4, 5};
        std::cout << v << '\n';
    }
}

int main()
{
    using namespace printable;

    std::vector v{1, 2, 3, 4, 5};
    std::cout << v << '\n';

    my::works::print_vec();
    my::suddenly_works::print_vec();
    my::fails::print_vec();
}

I tried to understand how ADL and overload resolution works, bu can't wrap my had around it yet. Also, googling gave me nothing.

0

There are 0 answers