
Le 8 oct. 2014 à 15:33, Joaquin M Lopez Munoz <joaquin@tid.es> a écrit :
I expect the flyweight implementation to support inheritance, just as
std::shared_ptr<base> p = std::make_shared<derived>();
This is alas not the case for flyweight<base>/flyweight<derived>. You can simulate something like that behavior in poly_flyweight:
template<typename Derived> class poly_flyweight { ... operator flyweight<Base>()const; ... };
but invoking this operator for a poly_flyweight<Derived> object x would imply creating a clone of x.get() (upcasted to const Base*) in poly_flyweight<Base> internal factory, which is a waste of space and brings you to the original situation where all objects are stored in the same factory.
I used something more agressive: template <typename T> class poly_flyweight : public boost::flyweight<poly_holder<T>> { public: using super = boost::flyweight<poly_holder<T>>; using super::super; /// Conversion to superclass. template <typename U> operator const poly_flyweight<U>&() const { const void* me = this; return *static_cast<const poly_flyweight<U>*>(me); } const T& operator*() const { return base(); } const T* operator->() const { return &base(); } private: const T& base()const { return this->get(); } }; of course I need to enable this conversion only when one can convert from T to U. However, while this adresses: NumFW a = num(1); Exp b = a; it does not work for: Exp c(a); even if I try to add a constructor to the poly_flyweight: template <typename U> explicit poly_flyweight(const poly_flyweight<U>& x) : poly_flyweight(static_cast<const poly_flyweight&>(x).base()) {} I have to make it explicit to avoid ambiguities, but then my ctor is never ever called. I suspect that there is a perfect forwarding constructor inside boost::flyweight that is preferred by the compiler. I have quite a headhack now, I gotta stop :) Again, thanks a lot Joaquín. (Actually it looks like what I did is not even portable: my clang 3.5 is happy with it, but not Coliru's gcc http://coliru.stacked-crooked.com/a/0cfe34a8ba934fea)