
De: Boost-users [mailto:boost-users-bounces@lists.boost.org] En nombre de Akim Demaille Enviado el: martes, 07 de octubre de 2014 18:27 Para: Boost Users List Asunto: Re: [Boost-users] Flyweight: wrapping shared_ptr
Le 7 oct. 2014 à 18:18, Joaquín Mª López Muñoz <joaquin@tid.es> a écrit :
An alternative would be to use some sort of cloning smart pointer to spare the reference count, but it's not clear to me this would be faster than shared_ptr:
* element exists: shared_ptr creation is slower than clone_ptr creation * element does not exist: shared_ptr creation and copy is probably faster than clone_ptr creation and cloning.
Yes, indeed.
A slightly smarter approach involves a cloning class that accepts a const Base& and does only clone on copy, thus avoiding dynamic memory allocation when the element already exists. This can be nicely wrapped up as follows: template<typename Base> class poly_holder { public: poly_holder(const Base& x):p(&x),dlt(false){} poly_holder(const poly_holder& x):p(x.p->clone()),dlt(true){} poly_holder& operator=(const poly_holder& x) { Base* q=x.p->clone(); if(dlt)delete p; p=q; dlt=true; return *this; } ~poly_holder(){if(dlt)delete p;} operator const Base&()const {return *p;} private: const Base* p; bool dlt; }; template<typename Base> class poly_flyweight:public boost::flyweight<poly_holder<Base>> { public: using super=boost::flyweight<poly_holder<Base>>; using super::super; const Base& operator*() const{return base();} const Base* operator->()const{return &base();} private: const Base& base()const{return this->get();} }; template<typename Base> std::size_t hash_value(const poly_flyweight<Base>& x) { return boost::hash<const Base*>()(&*x); } template<typename Base> bool operator==( const poly_flyweight<Base>& l,const poly_flyweight<Base>& r) { return static_cast<boost::flyweight<poly_holder<Base>>>(l)== static_cast<boost::flyweight<poly_holder<Base>>>(r); } template<typename Base> bool operator!=( const poly_flyweight<Base>& l,const poly_flyweight<Base>& r) { return !(l==r); } I've rewritten your test case to take advantage of this poly_flyweight thing, cleaning up some unnecessary hash and operator== overloads along the way and without resorting to the intermediate Exp_ type; see: http://coliru.stacked-crooked.com/a/76e87531b65d44f9
Is there anyway Flyweight could have supported the operator-> natively? It seems that with some SFINAE under the hood, it would work, don't you think?
Yep, that would be possible, the only reason I didn't do it is to not clutter the interface. Also, some std classes such as (C++17) std::optional implement operator* differently, without the extra dereference required by smart pointer semantics. Joaquín M López Muñoz Telefónica