以下代码有效,但我想移动ostream&运营商LT;<除了我在hash :: operator []。
之外的类declearation#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;
}
我试过了:
template <class T>
ostream& operator<<(...) {
return out << "test";
}
和
ostream& operator<<(...) {
return out << "test";
}
以及其他一些组合无济于事。
答案 0 :(得分:6)
由于这个问题似乎并未完全复制,我将解释您的计划的作用。
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;
}
模板按需实例化(除非您显式实例化它们),这意味着在此特定程序中test
仅实例化为test<int>
。当编译器实例化模板时(因为它是在main
中请求的),它将处理模板定义。此时,行为类似于在定义时使用替换类型重写代码(在这种情况下恰好在main
之前):
class test<int> {
friend std::ostream& operator<<( std::ostream&, test<int> const & );
};
现在,如果查看实例化模板,您可以注意到friend
声明与非模板化函数成为友好关系。因此,在此特定程序中,您可以使用该特定函数填充???
:
std::ostream& operator<<( std::ostream& o, test<int> const & t ) {
return o << t.private_field;
}
这里的问题是这不容易扩展。 operator<<
的{{1}}代码与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 & ) { ... }
当然还有另一种选择:根本不要声明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 & ) { ... }
。在您的类中提供具有实现的friend
公共函数,并提供一个非模板print(std::ostream&)
,只在第二个参数上调用operator<<
。
答案 1 :(得分:3)
使用朋友和模板
时必须小心#include<iostream>
#include<map>
template <class T>
class MyHash{
public:
// ... use your T template here
template <class U>
friend ostream& operator<<(ostream& out, const MyHash<U> &rhs);
};
// ...
template <class U>
ostream& operator<<(ostream& out, const MyHash<U> &rhs){ return out << "test"; }
您需要使用其他模板U ,因为运算符&lt;&lt; 是朋友方法(外部),如果我们使用 T 而不是 U ,我们将:模板中的模糊定义。
通过 MyHash 更改哈希,以避免含糊不清。
修改:
您获得的错误here是:
错误C2676:'&lt;' binaire:'std ::string'nedéfinitpascetopérateur ou une转换为un type type pour l'opérateurprédéfini
因为您忘记将<string>
包含在“hash.h”中。该标题定义&lt;操作即可。
并尝试将运算符[] 和运算符&lt;&lt; 的定义直接移至“hash.h” 必须包含模板的声明和定义。这是因为在某些编译器中,模板函数无法独立编译和链接,因为它们是根据请求生成的特定类型生成的。
将 #include“hash.cpp”更改为 #include“hash.h”