繼續上篇的 FoldingSet 學習。緩存
== ContextualFoldingSet ==
ContextualFoldingSet 模板類提供對 FoldingSet 的一些改進,其在調用 Profile() 等方法的時候提供一個 context(上下文、環境) 參數。模板類 T 必須繼承自 FoldingSetNode,並實現 Profile(ID, Ctx) 簽名的方法。數據結構
類概要以下:
<syntaxhighlight lang="cpp">
template<T, CTXT>
class ContextualFoldingSet : public FoldingSetImpl {
// 原註釋稱不能從 FoldingSet<> 繼承,由於裏面的 Profile 函數沒有 ctxt 參數。
CTXT Context; // 此 FoldingSet 對應的環境,構造的時候初始化。app
// 重載基類方法,實現帶 Context 參數的 Profile() 方法調用。
virtual GetNodeProfile(Node *, ID)
virtual NodeEquals() // 實現爲帶 ctx 參數的 Equals() 調用
virtual ComputeNodeHash() // 實現爲帶 ctx 參數的 ComputeHash() 調用。函數
this(ctx, initS) // 構造函數,使用指定環境和初始尺寸。
iterator, bucket_iterator 等的定義
begin(),end(),bucket_begin(),bucket_end() 等迭代器實現學習
GetOrInsertNode(),FindNodeOrInsertPos() 同 FoldingSet
}
</syntaxhighlight>this
* 注1:構造函數實現中要求 CTXT 類實現複製構造語義。
* 注2:FoldingSet, ContextualFoldingSet 提供兩種迭代器,對 Node 的 iterator,對 bucket 內的節點遍歷的 bucket_iterator。這和其內部使用的數據結構有關。問題是,提供的 bucket_iterator 在什麼地方用呢?爲何要用呢?指針
這個類在內部多了一個 Context(上下文,環境),並在 Profile(), Equals(), ComputeHash() 調用中都帶有此參數。比起 FoldingSet 可能適用範圍更廣一些。繼承
也許由於 FoldingSetImpl 有兩個子類:FoldingSet, ContextualFoldingSet,所以使用了 virtual 的析構、GetNodeProfile() 等方法讓子類重載。若是使用模板也許會致使代碼太大?get
== FoldingSetIteratorImpl ==
這個類用於實現 FoldingSet 中節點(Node)的迭代器。it
實現的核心是 advance() 方法,當在 Node 鏈的時候,向後查找;不然找下一個有節點的桶。
這與 FoldingSet 中使用的數據結構相關。這裏不詳細說明了。
== FoldingSetIterator ==
模板類 FoldingSetIterator<T> 從 FoldingSetIteratorImpl 繼承,提供構造,*, ->, ++, ++(int) 的實現。
其實現爲一個 forward_iterator.
== FoldingSetBucketIteratorImpl ==
這個類提供公共的 bucket 桶內節點鏈表的迭代器基類。其可以遍歷 foldingset 哈希表中的桶內節點。提供了兩種構造,估計是爲了支持 begin(), end() 的實現(參見 FoldingSet 中的代碼)。
核心方法是 advance(),其遍歷其下一個節點指針(getNextInBucket())。
== FoldingSetBucketIterator ==
相似於 FoldingSetIterator。從 FoldingSetBucketIteratorImpl 繼承,提供構造,*, ->, ++, ++(int) 實現。
== FoldingSetNodeWrapper ==
FoldingSetNodeWrapper 類用於"包裝"(warp)任意類型,使其可以插入到 FoldingSet 中。
<syntaxhighlight lang="cpp">
template<T> class FoldingSetNodeWrapper : public FoldingSetNode {
T data; // 數據包裝進來。
this(const T&) // 構造函數,須要 T 實現複製構造語義。
virtual ~this() // 虛析構。爲何?
template<A1,[A2,A3,A4...]>this(A1&[,A2&,A3&,A4&...]) // 多種形態的構造,方便 data 的不一樣構造方式。
Profile(ID) // 實現對 data 的 ID 信息生成。
getValue(), T&() // 獲取 data 的方法。
}
</syntaxhighlight>
將 T data 封裝起來,經過特化 FoldingSetTrait<T> 提供 Profile() 方法外部的實現,這樣不用 T 實現 Profile() 方法(也許 T 是別人寫的,其沒有 Profile 方法)。
== FastFoldingSetNode ==
類 FastFoldingSetNode 是 FoldingSetNode 的子類,其保存(緩存) FoldingSetNodeID 的值,這樣不用每次都調用 Profile 方法去計算。此方式是空間換時間,對於 ID 很長生成成本高的時候有用,於是也容許節點釋放掉那些不須要產生 ID 的那些信息(字段、數據)。
然而在實現的 Profile() 函數中,採用的 ID.AddNodeID() 方法,仍然將整個 ID 內容複製了一份,也許應該有更好的辦法?例如引用而非複製?
== FoldingSetTrait<T*> == 這是對 FoldingSetTrait 的特化,適合於指針類型。實現的 Profile() 方法實際爲: ID.AddPointer(T*) 也即在 ID 中只存在一個指針。通常不用爲每種指針特定實現 Trait 特化了。