Le 8 oct. 2014 à 15:33, Joaquin M Lopez Munoz 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
{
public:
using super = boost::flyweight;
using super::super;
/// Conversion to superclass.
template <typename U>
operator const poly_flyweight<U>&() const
{
const void* me = this;
return *static_cast(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(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)