我有一個定義了簡單的模板類。在這個類中,我定義了一個用於圖的節點的結構(struct NodeData)。對於我給出的第一個代碼,沒有編譯錯誤,即使我在方法測試中做了一個錯誤(我做了g[nId].anything = "something"
,即使struct NodeData沒有一個叫做任何變量的變量)。在類模板外部或內部定義的結構體
爲了理解問題出在哪裏,在第二個代碼中,我給出了下面的代碼,我把我的結構體定義和typedef放在了MyClass之外。我已經把template<typename T1, typename T2>
置於struct NodeData的定義之上,因爲這個結構需要存儲2個抽象類型T1和T2的變量。我還從typedefs中刪除了關鍵字typename
,並且我在第一個typedef中放入了NodeData<int, int>
而不是NodeData
(即使我實際上不想這樣做),否則它會在此行中提供一些錯誤,如:expected a type, got 'NodeData'
。當我編譯時,它會給出以下預期錯誤(實際上完全正常):'struct NodeData<int, int>' has no member named 'anything'
,而對於第一個代碼,我沒有得到這個錯誤!
這兩個代碼有什麼區別?我該如何做第二個代碼,不必爲第一個typedef指定NodeData(因爲struct 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()
{
// ...
}
你真的在第一種情況下調用void MyClass :: test(T1 arg1,T2 arg2)函數嗎?如果沒有,它不會被實例化,因此代碼中沒有錯誤 –
P3trus
嗯,我沒有實例化它,我仍然在爲它編寫代碼。那麼最後第一個代碼是完全正確的? – shn
不,它不正確,但編譯器無法看到錯誤,因爲他沒有使用它。 – P3trus