eve*_*992 3 c++ generics templates friend
下面的代码可以正常工作,但我想将ostream&operator <<移到类declearation之外,就像我使用hash :: operator []一样.
#include<iostream>
#include<map>
using namespace std;
template <class T>
class hash {
private:
map<string, T> _map;
public:
T& operator[] (string x);
friend ostream& operator<<(ostream& out, const hash<T> &rhs) { return out << "test"; }
};
template <class T>
T & hash<T>::operator[](string x) {
return _map[x];
}
int main () {
hash<int> myobject;
myobject["a"] = 1;
cout << myobject["a"] << endl;
cout << myobject << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我试过了:
template <class T>
ostream& operator<<(...) {
return out << "test";
}
Run Code Online (Sandbox Code Playgroud)
和
ostream& operator<<(...) {
return out << "test";
}
Run Code Online (Sandbox Code Playgroud)
以及其他一些组合无济于事.
由于这个问题似乎并未完全复制,我将解释您的程序的作用.
template <typename T>
class test {
int private_field;
friend std::ostream& operator<<( std::ostream&, test<T> const & );
};
// ???
int main() {
std::cout << test<int>() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
模板按需实例化(除非您明确实例化它们),这意味着在此特定程序中test仅实例化为test<int>.当编译器实例化模板时(因为它被请求main),它将处理模板定义.此时,行为类似于在定义时使用替换类型重写代码(在此情况下恰好在此之前main):
class test<int> {
friend std::ostream& operator<<( std::ostream&, test<int> const & );
};
Run Code Online (Sandbox Code Playgroud)
现在,如果您查看实例化模板,您可以注意到friend声明与非模板化函数成为友好关系.因此,在这个特定的程序中,您可以???使用该特定函数填写:
std::ostream& operator<<( std::ostream& o, test<int> const & t ) {
return o << t.private_field;
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是这不容易扩展.的该代码operator<<都是相同的test<int>比对test<double>,所以应该没有必要重写相同的功能适用于所有类型的实例!
此时有两个选项,第一个是,正如您已经确定的那样,在类中提供函数的定义.然后,只要实例化类型,编译器就会处理并定义函数.这个解决方案根据需要为每个模板实例化创建非模板化函数(这是我会做的选项,即使这里有查询的奇怪和奇怪).
现在,如果您真的想避免在模板类中提供定义,并且您仍希望提供单个实现,那么您必须使用提供模板operator<<.此时您有两个不同的选项,您可以声明模板的所有实例化(我不太喜欢,因为它打开了太多其他实例),或者您可以与模板功能的单一专业化(关于访问的清洁) ,写起来比较麻烦).
第一种情况是:
template <typename T>
class test {
template <typename U>
friend std::ostream& operator<<( std::ostream&, test<U> const & );
};
template <typename T>
std::ostream& operator<<( std::ostream&, test<T> const & ) { ... }
Run Code Online (Sandbox Code Playgroud)
第二种情况需要几个前瞻性声明:
template <typename T> test;
template <typename T> std::ostream& operator<<( std::ostream&, test<T> const & );
template <typename T>
class test {
friend std::ostream& operator<< <T>( std::ostream&, const test<T>& );
};
template <typename T>
std::ostream& operator<<( std::ostream&, test<T> const & ) { ... }
Run Code Online (Sandbox Code Playgroud)
当然还有另一种选择:根本不申报friend.print(std::ostream&)在类中提供具有实现的公共函数,并提供operator<<仅print在第二个参数上调用的非模板化函数.