Akim Demaille
Le 8 oct. 2014 à 14:32, Joaquin M Lopez Munoz
a écrit : Ah, you should add a move ctor and assignment operator for better performance. Revised example:
Great :) Finally, the free-lunch is not over, I should just let time pass and have my implementation improve all by itself :)
Anyway, please profile against shared_ptr, I'm not claiming this is necessarily faster.
Do you mean having
using ExpBin=poly_flyweight<Bin>; using ExpNum=poly_flyweight<Num>;
rather than a single using ExpBin=poly_flyweight<Bin>? I think this is very hard to manage: to begin with, Bin has two Exp members, with this type splitting it is not even clear how you would manage the different cases where the operands to Bin are compound expressions or Num's (and the combinations thereof).
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. A less ambitious approach is
template
So, there is a choice between having -> behave with "pointer semantics" (std::optional) or "pass-thru" semantics, for want of a better name.
Ouhh, I clearly prefer the pass-thru semantics here. The Flyweight is similar (to my eyes) to a proxy to an object that does all it can to have the rest of the code believe it is the real object. I'm very happy that I can enable/disable flyweight'ing via a simple typedef, and using a pointer-like semantics would break everything: the real object and the flyweight'ed one would have different interfaces.
I understand your rationale, but pass-thru semantics is only applicable to pointer-like elements.
If we choose pass-thru semantics, then we're ruling out the possibility of having operator-> in instantiations such as, say, flyweight<int>, where the flyweight'd element is not a (smart) pointer.
I'm not sure I understand what you mean here. I can't imagine what 'flyweight<int>(42)->...' would mean. I'd sfinae it out of the picture.
int is a poorly chosen example. Take instead
struct foo
{
int x;
};
With pointer-like semantics, you have
flyweight<foo> f;
flyweight