我有一个定义的简单模板类。在此类中,我定义了一个用于图的节点的结构(struct NodeData)。对于我给出的第一个代码,即使我故意在方法测试中犯了一个错误,也没有编译错误(即使struct NodeData没有任何变量,我也执行g[nId].anything = "something"
)。
为了理解问题所在,在下面的第二个代码中,我将结构定义和typedef放在MyClass之外。我已将template<typename T1, typename T2>
放在结构NodeData的定义之上,因为此结构需要存储2个抽象类型T1和T2的变量。我还从typedef中删除了关键字typename
,并且在第一个typedef中放置了NodeData<int, int>
而不是NodeData
(即使我实际上不想这样做),否则它将在此行出现一些错误,例如:expected a type, got 'NodeData'
。当我编译时,它会给出以下预期错误(实际上完全正常):'struct NodeData<int, int>' has no member named 'anything'
,而对于第一个代码,我没有得到此错误!
这两个代码有什么区别?如何使第二个代码不必为第一个typedef指定NodeData(因为结构NodeData的成员var1和var2不一定是int类型)?或者,如何使第一个代码正常工作并检测到NodeData没有名为anything
的成员的错误?
第一个代码:
#include <iostream>
#include <boost/graph/adjacency_list.hpp>
using namespace std;
using namespace boost;
template<typename T1, typename T2>
class MyClass
{
public:
MyClass();
virtual ~MyClass();
void test(T1 p, T2 s);
protected:
struct NodeData
{
T1 var1;
T2 var2;
int var3;
};
struct EdgeData
{
int var;
};
typedef adjacency_list<setS, setS, undirectedS, NodeData, EdgeData> Graph;
typedef typename Graph::vertex_descriptor NodeDataID;
typedef typename Graph::edge_descriptor EdgeDataID;
typedef typename graph_traits<Graph>::vertex_iterator VertexIterator;
Graph g;
};
template<typename T1, typename T2>
void MyClass<T1, T2>::test(T1 arg1, T2 arg2)
{
NodeDataID nId = add_vertex(g);
g[nId].anything = "but anything is not in struct NodeData !";
g[nId].var1 = arg1;
g[nId].var2 = arg2;
g[nId].var3 = 55;
}
template<typename T1, typename T2>
MyClass<T1, T2>::MyClass()
{
// ...
}
template<typename T1, typename T2>
MyClass<T1, T2>::~MyClass()
{
// ...
}
第二个代码:
#include <iostream>
#include <boost/graph/adjacency_list.hpp>
using namespace std;
using namespace boost;
template<typename T1, typename T2>
struct NodeData
{
T1 var1;
T2 var2;
int var3;
};
struct EdgeData
{
int var;
};
typedef adjacency_list<setS, setS, undirectedS, NodeData<int, int>, EdgeData> Graph;
typedef Graph::vertex_descriptor NodeDataID;
typedef Graph::edge_descriptor EdgeDataID;
typedef graph_traits<Graph>::vertex_iterator VertexIterator;
template<typename T1, typename T2>
class MyClass
{
public:
MyClass();
virtual ~MyClass();
void test(T1 p, T2 s);
protected:
Graph g;
};
template<typename T1, typename T2>
void MyClass<T1, T2>::test(T1 arg1, T2 arg2)
{
NodeDataID nId = add_vertex(g);
g[nId].anything = "but anything is not in struct NodeData !";
g[nId].var1 = arg1;
g[nId].var2 = arg2;
g[nId].var3 = 55;
}
template<typename T1, typename T2>
MyClass<T1, T2>::MyClass()
{
// ...
}
template<typename T1, typename T2>
MyClass<T1, T2>::~MyClass()
{
// ...
}
最佳答案
如果没有模板的实例化,则不会生成代码,因此不会出现编译错误。这就是为什么通常拥有一些测试代码很重要的原因,这些代码可以对模板进行一些可能的实例化,并使用它们来确保您不会犯任何愚蠢的错误。
编辑:添加了一个使用一些代码的示例,以防不清楚我在说什么。
#include <iostream>
template<typename T1, typename T2>
class MyClass
{
public:
void Test(T1 p, T2 s);
protected:
struct NodeData
{
T1 var1;
T2 var2;
int var3;
};
private:
NodeData m_g;
};
template<typename T1, typename T2>
void MyClass<T1, T2>::Test(T1 arg1, T2 arg2)
{
// error C2039: 'anything' is not a member of 'MyClass<T1,T2>::NodeData'
m_g.anything = "but anything is not in struct NodeData !";
m_g.var1 = arg1;
m_g.var2 = arg2;
m_g.var3 = 55;
}
int main() {
// if you comment out the lines using it the template will never be compiled
MyClass<int, double> test; // instantiation of template with T1 = int and T2 = double
test.Test(42, 3.14); // calling Test function
std::cin.get();
return 0;
}
关于c++ - 在类模板外部或内部定义的结构,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8993877/