[英]How do you declare the friend of a generic class outside of the class decleration?
下面的代码可以正常工作,但我想将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;
}
我努力了:
template <class T>
ostream& operator<<(...) {
return out << "test";
}
和
ostream& operator<<(...) {
return out << "test";
}
以及其他一些组合无济于事。
由于这个问题似乎并未完全复制,我将解释您的程序的作用。
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;
}
这里的问题是这不容易扩展。 对于test<int>
,该operator<<
的代码与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<<
只调用第二个参数的print
。
使用朋友和模板时必须小心
#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,因为operator <<是朋友方法(外部),如果我们使用T而不是U ,我们将在模板中有: 模糊定义 。
通过MyHash更改哈希以避免歧义。
编辑:
你在这里得到的错误是:
错误C2676:'<'binaire:'std ::string'neéfinitpascetopérateurouune conversion vers un type acceptable pour l'opérateurprédéfini
因为你忘了在“hash.h”中包含<string>
。 该标题定义了<运算符 。
并且还尝试将operator []和operator <<的定义直接移动到“hash.h”中 。必须包含模板的声明和定义。 这是因为在某些编译器中,模板函数无法独立编译和链接,因为它们是在对实例化的特定类型的请求时生成的。
将#include“hash.cpp”更改为#include“hash.h”
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.