2011-09-28 143 views
1

填寫一個類的模板,如果我有兩類:從另一個模板類

template <typename T> 
struct Node 
{ 
    ... 
}; 

tempalte <typename T_Node, typename T> 
struct NodeIterator 
{ 
    T m_value; 
}; 

NodeIterator<Node<int>, int> 

我可以從T_Node推斷模板參數T無類Node明確創建這樣一個typedef:

// To make it clear, yes I know this works, but I had to typedef the type 
template <typename T> 
struct Node 
{ 
    typedef T node_type; 
    ... 
}; 

template <typename T_Node> 
struct NoteIterator 
{ 
    typedef typename T_Node::node_type node_type; 

    node_type m_value; 
}; 

NodeIterator<Node<int> > 

如果沒有,是否有一個原因,我不能這樣做(編譯器已經知道T_Node和類型T它參加了)除了「功能只是不存在於C++中「?我這樣問,通常情況下有一個簡單的理由(至少在表面上),就像這樣從語言中遺漏的東西。

+0

你試過了嗎?你得到了什麼錯誤? –

+0

我的句子有點含糊。我提出的解決方案的工作。我想知道是否有解決方案,我不需要鍵入typedef。 – Samaursa

+0

@Samaursa:你在'typedef T_Node :: node_type node_type;'中忘記了'typename'。看我的解決方案。 – Nawaz

回答

2

沒有typedef,這是不可能的。關鍵是編譯器不知道T_Node本身就是一個模板的實例化。 Node<T>只是類型,僅此而已。

C++知道三層實體:值,類型和模板。 Node是一個模板,而Node<T>是一個類型。當您的班級模板接受類型參數時,則無法檢查該類型的性質。

通過部分專業化進行模式匹配是提取此類信息的唯一方法,並且您無需掌握一點功能元編程。任何類型的檢查通常稱爲「類型特徵」。它都會歸結爲同樣的事情,非常相似,你已經建議,但也許這裏是另一個,更通用的方法:

template <typename> struct ClassWithOneArg; 

template <template <typename> class C, typename T> 
struct ClassWithOneArg<C<T>> 
{ 
    typedef T value_type; 
}; 

現在,你可以說:typedef typename ClassWithOneArg<T_Node>::value_type type;

2

爲什麼dont't更改NodeIterator以類似的東西:

template <typename T> 
struct NodeIterator 
{ 
    typedef Node<T> node_type; 

    node_type m_value; 
}; 

這應該允許您創建類型NodeIterator<int>的對象。我認爲這將是一個優雅的解決方案。 `

+0

因爲我不想'NodeIterator'知道'Node' – Samaursa

+0

這是爲什麼?看看STL,迭代器甚至可以在它們相應的容器中定義,因此可以分享非常密切的關係。 – Constantinius

+0

此外,由於你的'T_Node'預計有一個'typedef',它叫做'node_type',所以你提出的解決方案會有兩個類的緊密耦合。 – Constantinius

1

是。什麼你試過幾乎是正確的,但你忘了typename

typedef typename T_Node::node_type node_type; 
     //^^^^^^^ note this! 

你需要寫關鍵字typename因爲嵌套式node_type是依賴

+1

這個問題已經提出了這個答案。 –

+0

@MarkRansom:我誤解了這個問題。無論如何,糾正它。 – Nawaz

+1

啊,是臭名昭着的'typename'關鍵字:)我會在我的問題(+1)中糾正它, – Samaursa

0

不,你不能。你需要typedef。 C++沒有任何編譯時反射支持,這個功能很適合。

它不在語言中的原因很簡單:在標準化過程中沒有人提出這樣一個功能的好建議。這可能是因爲這樣的功能並不重要。爲什麼你可能只是樂於接觸模板參數,還有很多其他地方需要考慮使整個功能看起來「圓」。

intrested時,你可以制定出這樣的建議;)

0

我不認爲你可以,但我不認爲你應該需要可以。爲此使用typedefs是一個行之有效的做法;看看標準容器和它們的value_type等typedefs。

您在對另一個答案的評論中提及您不希望NodeIterator知道關於Node。它不必特別瞭解Node;它只是要求其模板參數爲某些類型,其中包含node_type類型。那可能是Node或者它可能是別的,NodeIterator不必知道或關心。

0

答案是否定的,你不能在C++中做到這一點。這就是爲什麼STL迭代器類型包含您試圖避免的嵌套typedef的原因。另外,如果你想允許指向節點的指針(這符合RandomAccessIterator的所有要求),那麼依賴這些嵌套類型會給你帶來麻煩。如果您想將節點的原始指針包含爲節點迭代器類型,則需要使用traits類,因爲它們不能有嵌套類型。

相關問題