在用C++編寫coroutine基礎類的時候,需要參數的傳遞。
而基礎類對參數類型一無所知,畢竟參數是與應用相關的。
此時,boost::any就派上用場了。
編寫此類的時候並沒有參考boost::any代碼(因此功能肯定不如boost::any完善嚴謹),寫完後做了一下參考,將命名向boost看齊
1. 先思考一下Any的用法:
Any obj;obj = 5;cout << any_cast<int>(obj) << endl;obj = string("hello");cout << any_cast<string>(obj) << endl;int* p = new int(5);obj = p;cout << *any_cast<int*>(obj) << endl;
如上所示,obj可以被賦予“任何”類型的值:int,string,int*;
使用者必須清楚any的底層類型,以在使用時候做cast轉換(畢竟C++是強型別語言)。
不難推斷出any實現使用了模板operator=;(還有模板建構函式,同理)
具有以下籤名函數
template <typename T>Any& operator=(const Any& rhs);
且Any本身是一個普通類,不能是模板類 (由Any obj;聲明推斷)
這裡引來了一個問題:
既然any不是模板類,如何儲存任意的資料類型?
畢竟常規都是這麼做的:
template <typename T>class Any{ T value;};
有個辦法可以解決:讓模板類繼承自普通類:
class DummyHolder{public: virtual ~DummyHolder() { } virtual DummHolder* Copy() const = 0;};template <typename T>class Holder : public DummyHolder{ .... T value;};
這樣,在any類中添加一個唯一成員:
DummyHolder* pHolder;
any類的模板建構函式如下:
template <typename T> Any(const T& value) : pHolder(new Holder<T>(value)) { }
這樣的話,形如 Any obj(5);聲明就合法了。
水到渠成,operator=實現如下:
Any& operator= (const Any& that) { if(this == &that) return *this; delete pHolder; pHolder = (that.pHolder ? that.pHolder ->Copy() : 0); return *this; }
至此,基礎any類完成了,下面還需要使用它,轉為我們需要的類型,實現很簡單,不說了。
唯一注意的是,需要將參考型別的引用“剝去”;
boost的實現很複雜,很全面。
我隨手寫了幾行基本能用:
template <typename T>struct remove_ref{ typedef T noref_type;};template <typename T>struct remove_ref<T& >{ typedef T noref_type;};
只需要對參數T做“剝去”動作即可:
typedef typename remove_ref<T>::noref_type noref_t;
PS:寫模板的時候經常遇到一些匹配錯誤,特別是遇到一族偏特化的模板。
調試代碼中加入typeid(T).name()會有一些協助。