如果您真的想在外部定义运算符并且只与类型与此模板实例化一致的运算符实例化,正确的语法是:
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<<
,这已经是一个足够长的列表)。