C++ 模板和继承类中ostream重载中的重新定义错误

C++ 模板和继承类中ostream重载中的重新定义错误,c++,templates,inheritance,ostream,C++,Templates,Inheritance,Ostream,我试图在模板和继承类中重载ostream操作符,我一直在遵循一些技巧和方法,但我得到了一个重新定义错误。这是我的代码的复制品: #include <iostream> enum type { A, B }; template <type T> class base { protected: virtual std::ostream& print(std::ostream& out) const =0; }

我试图在模板和继承类中重载ostream操作符,我一直在遵循一些技巧和方法,但我得到了一个重新定义错误。这是我的代码的复制品:

#include <iostream>

enum type
{
        A,
        B
};

template <type T>
class base
{
protected:
        virtual std::ostream& print(std::ostream& out) const =0;
};

template <type T>
class derived: public base<T>
{
protected:
        virtual std::ostream& print(std::ostream& out) const
        {
                out<<"Hello World.\n";
                return out;
        }
public:
        template <type S>
        friend std::ostream& operator<<(std::ostream& out, const derived<S>& D)
        {
                return (D.print(out));
        }
};

int main ()
{
#ifdef __NOT_WORKING__
        derived<A> a;
        std::cout<<a;
        derived<B> b;
        std::cout<<b;
#else
        derived<A> a;
        std::cout<<a;
#endif
        return 0;
}
#包括
枚举类型
{
A.
B
};
样板
阶级基础
{
受保护的:
虚拟std::ostream&print(std::ostream&out)常量=0;
};
样板
派生类:公共基
{
受保护的:
虚拟std::ostream&print(std::ostream&out)常量
{
取出更换

template <type S>
friend std::ostream& operator<<(std::ostream& out, const derived<S>& D)
{
    return (D.print(out));
}
模板
friend std::ostream&operator[temp.friend]/4:

在类的友元函数声明中定义函数时 模板,当函数被odr使用时,函数被实例化。 对多个声明和定义的限制与 适用于非模板函数声明和定义也适用 与这些隐含的定义相对应。

Clang编译了上面的细节——这可以被认为是一个bug,但是回想一下,违反ODR的行为是不正确的,不需要诊断


有两种方法可以解决此问题。提取模板的定义:

template <typename T>
class derived: public base<T>
{
//     [..]

       template <type S>
       friend std::ostream& operator<<(std::ostream& out, const derived<S>& D);
};

template <type S>
std::ostream& operator<<(std::ostream& out, const derived<S>& D)
{
    return (D.print(out));
}
模板
派生类:公共基
{
//     [..]
样板
friend std::ostream和操作员
friend std::ostream& operator<<(std::ostream& out, const derived<T>& D)
{
    return (D.print(out));
}
template <typename T>
class derived: public base<T>
{
//     [..]

       template <type S>
       friend std::ostream& operator<<(std::ostream& out, const derived<S>& D);
};

template <type S>
std::ostream& operator<<(std::ostream& out, const derived<S>& D)
{
    return (D.print(out));
}
template <type T>
class derived: public base<T>
{
//     [..]

       friend std::ostream& operator<<(std::ostream& out, const derived<T>& D)
       {
               return (D.print(out));
       }
};