ostream 运算符<<从不同命名空间使用时解析失败

ostream operator<< resolution fails when used from different namespaces

提问人:Joshua Jakowlew 提问时间:8/17/2023 最后编辑:Alan BirtlesJoshua Jakowlew 更新时间:8/17/2023 访问量:62

问:

我在命名空间中为 for 进行了重载。 据我了解,ADL 不会隐式看到这个重载,因为不是 的成员,所以我们必须在调用代码时使用命名空间来查看这个重载。ostream operator<<std::vectorprintablestd::vectorprintableprintable

在其他命名空间中,我为我的类定义了另一个重载。在那之后,代码中断并且无法编译。my::failsfoo

在命名空间中,我没有使用整个命名空间,只有 ,并且...一切都还好。为什么?有什么区别。my::suddenly_worksprintableoperator<<

在那之后,我没有定义任何附加重载,而只是使用命名空间,使用重载运算符。一切都很好,正如预期的那样。my::worksprintable

所以,问题是:如何正确地在命名空间中重载未在此命名空间中定义的类型,以及如何在调用端的另一个命名空间中使用这些重载。ostream operator<<

另外,作为一个附带问题,在给定的例子中和有什么区别?using namespace printableusing printable::operator<<

这是代码(godbolt 链接):

#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();
}

我试图了解 ADL 和过载解决方案的工作原理,但 bu 还不能将我的 have 包裹起来。另外,谷歌搜索什么也没给我。

c++ 运算符重载 iostream 参数-dependent-lookup

评论

1赞 Jarod42 8/18/2023
Using-declarationsUsing-directives
0赞 Davis Herring 8/18/2023
为什么不专门工作?usingoperator<<

答: 暂无答案