C++ 从std::ostream派生的自定义流的编译问题

C++ 从std::ostream派生的自定义流的编译问题,c++,g++,operator-overloading,clang++,ostream,C++,G++,Operator Overloading,Clang++,Ostream,最近,我编写了一些代码,创建了一个从std::ostream派生的自定义流。 它使用clang++12.0进行编译,而使用g++10.1进行编译失败 在这两种情况下,我都使用g++附带的libstdc++。此外,我为这两个编译器指定了以下参数:-std=c++20-Wall-Wextra-Wpedantic 以下代码是最小的可复制示例: #include <ostream> #include <vector> template <typename T> st

最近,我编写了一些代码,创建了一个从std::ostream派生的自定义流。 它使用clang++12.0进行编译,而使用g++10.1进行编译失败

在这两种情况下,我都使用g++附带的libstdc++。此外,我为这两个编译器指定了以下参数:-std=c++20-Wall-Wextra-Wpedantic

以下代码是最小的可复制示例:

#include <ostream>
#include <vector>

template <typename T> std::ostream& operator<<(std::ostream& s, const std::vector<T>&) 
{
    return s;
}

struct CustomStream : std::ostream {};

template <typename T> CustomStream&& operator<<(CustomStream&& s, const T& v) 
{
    static_cast<std::ostream&>(s) << v;
    return std::move(s);
}

int main() 
{
    CustomStream() << std::vector<int>{};
}

因此,g++似乎无法找到第一个不确定为什么不同的编译器会产生不同的结果,但显然,它与来自ostream的:

为了避免这种情况,您可以将代码包装到自己的名称空间中,并享受ADL魔力:

#include <ostream>
#include <vector>

namespace CS
{
    template <typename T>
    std::ostream &operator<<(std::ostream &s, const std::vector<T> &)
    {
        return s;
    }

    struct CustomStream : std::ostream
    {
    };

    template <typename T>
    CustomStream &&operator<<(CustomStream &&s, const T &v)
    {
        static_cast<std::ostream &>(s) << v;
        return std::move(s);
    }
}
int main()
{
    CS::CustomStream() << std::vector<int>{};
}
template <typename T> CustomStream& operator<<(CustomStream& s, const T& v) 
{
    static_cast<std::ostream&>(s) << v;
    return s;
}

int main() 
{
    CustomStream s;
    s << std::vector<int>{};
}
#include <ostream>
#include <vector>

namespace CS
{
    template <typename T>
    std::ostream &operator<<(std::ostream &s, const std::vector<T> &)
    {
        return s;
    }

    struct CustomStream : std::ostream
    {
    };

    template <typename T>
    CustomStream &&operator<<(CustomStream &&s, const T &v)
    {
        static_cast<std::ostream &>(s) << v;
        return std::move(s);
    }
}
int main()
{
    CS::CustomStream() << std::vector<int>{};
}