4

如何在模板类中重载插入 (<<) 和/或提取 (>>) 运算符而不使其内联。我希望将 << 或 >> 运算符作为朋友类。我知道如何使它成为矩阵类中内联的内联示例

friend ostream& operator<<(ostream& ostr, const Matrix<T>& inputMatrix)
{
   ...
   // create the ostr
   return ostr;
}

但我想将代码放在模板类定义之外。

g++ 告诉我在函数名之后添加 <>,所以我这样做了,但是当我尝试实例化 SOMETYPE 类型的矩阵时,它给了我一个错误,它不知道如何为该类型提取或插入。

4

3 回答 3

2

尝试类似:

template <typename T> class Matrix;
template <typename T> std::ostream& operator<<(std::ostream& ostr, const Matrix<T>& m);

template <Typename T>
class Matrix
{
    public:

        friend ostream& operator<< <T> (ostream& ostr, const Matrix<K>& inputMatrix);
};

// This must be in the same translation unit as the class definition!
template<typename T>
ostream& operator<<(ostream& ostr, const Matrix<T>& inputMatrix)
{
   // ...
   return ostr;
}

翻译单元参考

重新编辑以解决 aschepler 和 dribeas 的评论。

于 2010-11-09T19:23:42.130 回答
2

如果您真的想在外部定义运算符并且只与类型与此模板实例化一致的运算符实例化,正确的语法是:

template <typename T> class test; // forward declare template class
template <typename T>              // forward declare the templated operator
std::ostream& operator<<( std::ostream&, test<T> const & );

template <typename T>
class test {                      // define the template
   friend std::ostream& operator<< <T>( std::ostream&, test<T> const & ); // befriend
};
template <typename T>              // define the operator 
std::ostream& operator<<( std::ostream& o, test<T> const & ) {
   return o;
}

在大多数情况下,将定义从类中提取出来是不值得的,考虑到您仍然需要在标题中提供它并且需要额外的工作。

另请注意,编译器在查找方面存在细微差别。在函数被内联在类定义中的情况下,编译器将不会找到该函数,除非其中一个参数实际上是模板的类型,因此它有效地减少了编译器的可见性和工作量做(如果模板operator<<是在类之外定义的,编译器会在它找到的所有地方发现它作为重载决议的候选者a << b,只是在第二个参数不是 a 的所有情况下丢弃它test<T>(它会显示模板化运算符作为它无法匹配的所有错误消息中的候选者operator<<,这已经是一个足够长的列表)。

于 2010-11-09T20:46:30.050 回答
1

将代码放在标题中,在类定义之外。或者,将其放在一个.tcc文件中并将其包含在标题的底部。

于 2010-11-09T19:17:39.540 回答