class any;
(since C++17)
The class any describes a type-safe container for single values of any type.c++
- (1) An object of class any stores an instance of any type that satisfies the constructor requirements or is empty, and this is referred to as the state of the class any object. The stored instance is called the contained object. Two states are equivalent if they are either both empty or if both are not empty and if the contained objects are equivalent.
- (2) The non-member any_cast functions provide type-safe access to the contained object.Implementations are encouraged to avoid dynamic allocations for small objects, but such an optimization may only be applied to types for which std::is_nothrow_move_constructible returns true.
能夠將any看做c++中的Object類(僅僅從功能上看),不過這個類的具體實現是經過模板包裝。
在閱讀Muduo網絡庫時,爲每一個線程保存的context就是經過any來實現的,STL中提供的泛型粒度太大,並且須要顯示指明模板類型(使用類型推斷+關鍵字auto如何?這樣咱們在存儲和取出該變量時又很麻煩),此時使用std::any。安全
- 實現思路
使用基類來包裝模板類隱藏掉泛型(利用any的模板構造函數傳入構造),而且提供一組虛函數接口。
class holder { public: virtual holder* clone() const = 0; virtual const std::type_info& type() const = 0; virtual ~holder() { } };
被包裝的模板類存儲類型實例,而且實現虛函數接口(克隆,返回類型ID等)網絡
template<typename value_type> class dataholder : public holder { private: typedef dataholder<value_type> self; public: dataholder(const value_type& v) :val(v) {} dataholder(const self&) = delete; self& operator = (const self& rhs) = delete; virtual dataholder* clone() const { return new dataholder(val); } virtual const std::type_info& type() const { return typeid(val); } value_type val; };
- any 的實現:
利用基類指針+ 模板 接受不一樣lei'xin
利用強制類型轉換來向下轉型(使用typeid實現類型安全)
class any { public: template<typename value_type> friend value_type& any_cast(const any& rhs); any() :content(nullptr) {} template<typename value_type> any(const value_type& val) :content(new dataholder<value_type>(val)) {} any(const any& rhs) { content = rhs.content->clone(); } any& operator=(const any& rhs) { any tmp(rhs); std::swap(*this, tmp); } ~any() { delete content; } const std::type_info& type() const { return content == nullptr ? typeid(void) : content->type(); } private: holder* content; }; template<typename value_type> value_type& any_cast(const any& rhs) { assert(typeid(typename value_type) == rhs.type()); return static_cast<dataholder<value_type>*>(rhs.content)->val; }