在下面的代码中,我有一个模板类,其中包含成员类型(struct Element)。我想重载运算符<<对于成员类型。但是,代码不会编译。
如果有人能指出我哪里出错了,我会很感激吗?
include <iostream>
using namespace std;
// fwd decl
template<class T> class CC;
// operator<< overload template for member type CC<T>::Element
template<class T>
ostream& operator<<(ostream& os, const typename CC<T>::Element& elm) {
return os << elm.val1 << "/" << elm.val2;
}
template<class T>
class CC
{
public:
struct Element { // type member
int val1;
int val2;
};
template<typename U>
friend ostream& operator<<(ostream& os, const typename CC<U>::Element& elm);
};
int main() {
CC<int>::Element elm{0,0};
cout << elm << endl; // does not compile due to this!
}
答案 0 :(得分:9)
模板参数不能从嵌套实体中推导出来(简短说明:不同模板实例化的类型可能是seame)。即,声明
template<typename U>
ostream& operator<<(ostream& os, const typename CC<U>::Element& elm);
是否永远不会考虑friend
,因为无法推断出类型U
。您可以通过将friend
运算符设为非模板来解决问题:
// ...
friend ostream& operator<<(ostream& os, const Element& elm) { ... }
// or
friend ostream& operator<<(ostream& os, const CC<T>::Element& elm) { ... }
// ...
但是,该功能需要在其声明中实施。
答案 1 :(得分:3)
您的问题在于以下代码
ostream& operator<<(ostream& os, const typename CC<T>::Element& elm) {
Element
位于非推断的上下文中。因此,无法推导出模板参数。而且由于使用显式模板参数调用operator<<
会非常难看(如果可能的话),我建议更改整体编码模式。
例如,您可以将elm
作为推导出的模板参数,例如
template<typename E>
friend ostream& operator<<(ostream& os, const E& elm);
而不是使用专门的结构从E中提取实际的U
。