Modern C++ Design 筆記 第十一章 MultiMethods(3)收藏

來源:互聯網
上載者:User

開始的第一方案的查詢時間達到了O(n),我們認為在類的數量比較少的時候是可行的。在進入了第二方案的時候,我們讓查詢速度時間縮短到了O(log(n)),如果我們要在這裡更進一步的話,那就應該是O(1)了。在這裡我們就繼續推出這個所謂的常數時間方案。

在第二方案的時候,我們需要對數時間的比較來得到答案,如果是常數時間,那必須摒棄這種比較。參照前面的思路繼續往下,前面的map如果改成hashtable應該就可以了,每次對key通用運算就得到了對應value(就是函數或者functor)而這裡的key就是兩個型別參數組成的pair。但是Hashtable帶來了一定的複雜性和不穩定性。這裡大名鼎鼎的Alex給出的更直接穩定的方案就是直接把每個類都添加進一個index,通過2個index在二維數組中找到對應的處理函數(或者Functor)。這裡有一張文中的:

可以看到如果以後的處理函數是Rectangle,Screen的話,我們就找1,1這個點。類似的如果處理Circle在Printer上列印的話,我們就找3,4這個點對應的函數。這個用空間換取時間的方案就是通過std::vector來實現的,下面就是具體的實現:

#define IMPLEMENT_INDEXABLE_CLASS(SomeClass)<br />static int& GetClassIndexStatic()/<br />254<br />{/<br />static int index = -1;/<br />return index;/<br />}/<br />virtual int& GetClassIndex()/<br />{/<br />assert(typeid(*this) == typeid(SomeClass));/<br />return GetClassIndexStatic();/<br />}<br />template<br /><<br />class BaseLhs,<br />class BaseRhs = BaseLhs,<br />typename ResultType = void,<br />typename CallbackType = ResultType (*)(BaseLhs&, BaseRhs&)<br />><br />class BasicFastDispatcher<br />{<br />typedef std::vector<CallbackType> Row;<br />typedef std::vector<Row> Matrix;<br />Matrix callbacks_;<br />int columns_;<br />public:<br />BasicFastDispatcher() : columns_(0) {}<br />template <class SomeLhs, SomeRhs><br />void Add(CallbackType pFun)<br />{<br />int& idxLhs = SomeLhs::GetClassIndexStatic();<br />if (idxLhs < 0)<br />{<br />callbacks_.push_back(Row());<br />idxLhs = callbacks_.size() - 1;<br />}<br />else if (callbacks_.size() <= idxLhs)<br />{<br />callbacks_.resize(idxLhs + 1);<br />}<br />Row& thisRow = callbacks_[idxLhs];<br />int& idxRhs = SomeRhs::GetClassIndexStatic();<br />if (idxRhs < 0)<br />{<br />thisRow.resize(++columns_);<br />idxRhs = thisRow.size() - 1;<br />}<br />else if (thisRow.size() <= idxRhs)<br />{<br />thisRow.resize(idxRhs + 1);<br />}<br />thisRow[idxRhs] = pFun;<br />}<br />ResultType Go(BaseLhs& lhs, BaseRhs& rhs)<br />{<br />int& idxLhs = lhs.GetClassIndex();<br />int& idxRhs = rhs.GetClassIndex();<br />if (idxLhs < 0 || idxRhs < 0 ||<br />idxLhs >= callbacks_.size() ||<br />idxRhs >= callbacks_[idxLhs].size() ||<br />callbacks_[idxLhs][idxRhs] == 0)<br />{<br />... error handling goes here ...<br />}<br />return callbacks_[idxLhs][idxRhs].callback_(lhs, rhs);<br />}<br />};<br />

類的index不是固定的,或者說並不是在TypeList中的index,因為我們這裡已經沒有TypeList了。現在需要主動需要植入每個class裡面,這也意味這原來非侵入式的平衡已經被打破了。每個類都需要申明這個宏。這裡的Matrix通過std::vector來組織,存放的具體內容就是CallbackType,當前這個BasicFastDispatcher類和原來的BasicDispatcher平行,也就是說可以通過Policy來進行替換,成為其他FnDispatcher的新的back end。在這裡的vector size的處理上有點小技巧,通過columns_來動態調整vector的size,而不是一上來就開出整個typelist長度的二維數組。同時也通過這個columns_來給classindex賦值。(注意這裡的GetClassIndexStatic函數返回的一直是int&)。還有一點就是出錯處理這裡沒有寫出來,但是不像原來的hatcher可以有個類,這裡都是對應的函數,所以一般我們會在這裡拋出一個異常。

Okay,我們就把所有的三個方案就介紹了一遍,這裡有一張圖涵蓋了對三種方式的特性的總結:

至此,我們對既有方案有一個全面的認識,從而為特定的case選擇的時候也有章可循了。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.