我正在研究一个模板Graph数据结构,它是GraphNode对象的STL向量。我定义了嵌套在Graph类中的GraphNode类,当我在Graph对象Visual Studio 15(C ++)报告的重载插入操作符内调用GraphNode对象的重载插入操作符时,
(30): warning C4346: 'myGraph<T>::myGraphNode': dependent name is not a type (30): note: prefix with 'typename' to indicate a type (30): error C2061: syntax error: identifier 'myGraphNode' (33): error C2805: binary 'operator <<' has too few parameters
template <typename T>
ostream& operator<<(ostream& strm, const myGraph<T>::myGraphNode& gn)
将单词typename添加到第二个形式参数
template <typename T>
ostream& operator<<(ostream& strm, typename const myGraph<T>::myGraphNode& gn)
编译器生成以下错误
(49): error C2679: binary '<<': no operator found which takes a right-hand operand of type 'const myGraph<int>::myGraphNode' (or there is no acceptable conversion)
如果我输入const ...或const typename ...
,我会得到同样的错误为了完整起见,这篇文章的所有代码都略有简化。 谢谢你的帮助
#include <iostream>
#include <vector>
#include <string>
using namespace std;
typedef unsigned int uint;
template <typename T>
class myGraph {
public:
class myGraphNode {
public:
myGraphNode(T val = T());
T mData;
}; // end class myGraphNode
myGraph();
uint addGraphNode(T data);
vector<myGraphNode> mGraphNodes;
}; // end class myGraph
// myGraphNode
template <typename T>
myGraph<T>::myGraphNode::myGraphNode(T val) : mData(val) {}
template <typename T>
ostream& operator<<(ostream& strm, typename const myGraph<T>::myGraphNode& gn) {
strm << gn.mData << std::endl;
return strm;
}
// myGraph
template <typename T>
myGraph<T>::myGraph() {}
template <typename T>
uint myGraph<T>::addGraphNode(T data) {
myGraph<T>::myGraphNode node(data);
mGraphNodes.push_back(node);
}
template <typename T>
ostream& operator<<(ostream& strm, const myGraph<T>& g) {
for (uint i = 0; i < g.mGraphNodes.size(); ++i)
cout << g.mGraphNodes[i] << endl;
return strm;
} // end operator<<(...)
int main()
{
myGraph<int> g;
g.addGraphNode(3);
g.addGraphNode(5);
cout << g << endl;
return 0;
}
答案 0 :(得分:1)
首先,参数声明的正确语法应为
template <typename T>
ostream& operator<<(ostream& strm, const typename myGraph<T>::myGraphNode& gn)
// ~~~~~ ~~~~~~~~
有关更多信息,请参阅here。
其次,根据上述声明,当尝试在operator<<
中为myGraph<T>
cout << g.mGraphNodes[i] << endl;
调用T
时,由于non-deduced contexts)无法推断operator<<<T>(strm, g.mGraphNodes[i]);
// ~~~
}:
嵌套名称说明符(范围解析运算符左侧的所有内容::)使用qualified-id指定的类型:
这意味着,您必须为其明确指定模板参数,例如
operator<<
但它很难看。对于您的情况,您可以为myGraph<T>
实施template <typename T>
ostream& operator<<(ostream& strm, const myGraph<T>& g) {
for (uint i = 0; i < g.mGraphNodes.size(); ++i)
cout << g.mGraphNodes[i].mData << endl;
return strm;
}
,例如
myGraph<T>::addGraphNode
BTW:您应该为{{1}}提供返回值。
答案 1 :(得分:1)
模板类型推导仅匹配模式。它不会反转依赖类型,因为(在一般情况下)是不可能的。
解决这个问题的方法是我称之为Koenig运算符的技术。
friend std::ostream& operator<<(std::ostream& strm, const myGraphNode& gn) {
strm << gn.mData << std::endl;
return strm;
}
将其放在myGraphNode
的正文中。
class myGraphNode {
public:
myGraphNode(T val = T());
T mData;
friend std::ostream& operator<<(std::ostream& strm, const myGraphNode& gn) {
strm << gn.mData << std::endl;
return strm;
}
}; // end class myGraphNode
这是一个非模板运算符,注入到可通过ADL访问的周围命名空间(仅)。这对于“它只是有用”来说是个奇特的词。