代码之家  ›  专栏  ›  技术社区  ›  Vincent

运算符模板类中的友元函数<<

  •  5
  • Vincent  · 技术社区  · 12 年前

    声明模板类的友元函数的正确方法是什么(对于std::ostream&operator<<) 在.cpp文件中 ?

    我目前的实施不起作用:

    // MyTest.h
    template<class T, unsigned int TSIZE> class MyTest
    {
        inline friend std::ostream& operator<< <T, TSIZE> (std::ostream &lhs, const MyTest<T, TSIZE> &rhs);
    };
    
    // MyTest.cpp
    template<class T, unsigned int TSIZE> inline friend std::ostream& operator<< <T, TSIZE> (std::ostream &lhs, const MyTest<T, TSIZE> &rhs)
    {
        // IMPLEMENTATION
    }
    
    2 回复  |  直到 2 年前
        1
  •  8
  •   Luc Danton    12 年前

    参考 operator<< <T, TSIZE> 就像您所做的那样,这是一个模板专用化,主模板的声明必须是可见的。反过来 operator<< 需要声明 MyTest 因为它显示为一个参数。

    // Declare MyTest because operator<< needs it
    template<class T, unsigned int TSIZE> class MyTest;
    
    // Declare primary template
    template<class T, unsigned int TSIZE>
    inline std::ostream& operator<<(std::ostream& lhs, const MyText<T, TSIZE>& rhs);
    
    template<class T, unsigned int TSIZE> class MyTest
    {
        // Specialization MyTest<T, TSIZE> only declares
        // specialization operator<< <T, TSIZE> as friend
        // Note that you can just use '<>' to designate the specialization,
        // template parameters are deduced from the argument list in this case
        inline friend std::ostream& operator<< <> (std::ostream &lhs, const MyTest<T, TSIZE> &rhs);
    };
    

    您的定义应该与这些声明相匹配。请注意,由于 运算符<< 是一个模板,它的定义很可能应该在标题中。

    在编写所有这些抢先声明时,需要较少工作的另一种选择是 MyTest<T, TSIZE> 将整个模板声明为朋友,而不仅仅是需要 我的测试<T、 尺寸>

    // in MyTest definition
    template<typename U, unsigned USIZE>
    inline friend std::ostream& operator<<(std::ostream& lhs, const MyTest<U, USIZE>& rhs);
    

    您所拥有的定义也应该与这样的声明相匹配(模板参数的名称与匹配的声明和定义无关)。

    为了完整起见,我将提到,当涉及到类模板的朋友时,另一种选择是在类模板定义中定义它。这定义了一个非模板朋友函数,该函数对于每个专业化都是唯一的。

    // in MyTest definition
    friend std::ostream& operator<<(std::ostream& lhs, MyTest const& rhs)
    { /* implementation */ }
    

    不可能提及此类功能(例如。 &ns::operator<< 不起作用,与其他选项不同),并且它们只能通过ADL找到。

        2
  •  0
  •   Kirill Kobelev    12 年前

    目前还不完全清楚最初的帖子想要什么。我认为它想要以下内容:

    // Some template class.
    template<class T, unsigned int TSIZE> class MyTest { };
    
    // Some template function.
    template<class T, unsigned int TSIZE> std::ostream& operator<< (std::ostream &lhs, const MyTest<T, TSIZE> &rhs)
    {
        // IMPLEMENTATION
    }
    

    现在有必要将此模板函数声明为类的友元,因为此函数需要访问的受保护对象 My test 这可以通过以下定义来实现:

    template<class T, unsigned int TSIZE> class MyTest
    {
        template<class T1, unsigned int TSIZE1> 
        friend std::ostream& operator<< (std::ostream &lhs, const MyTest<T1, TSIZE1> &rhs);
    };
    

    模板标头需要位于 friend 声明,因为这是一个不相关的模板函数,不属于当前模板类。