Boost logo

Boost Users :

Subject: Re: [Boost-users] Flyweight: wrapping shared_ptr
From: Akim Demaille (akim_at_[hidden])
Date: 2014-10-08 09:07:15


Le 8 oct. 2014 à 14:32, Joaquin M Lopez Munoz <joaquin_at_[hidden]> a écrit :

> Akim Demaille <akim <at> lrde.epita.fr> writes:
>
>>
>> Le 7 oct. 2014 à 20:41, Joaquin M Lopez Munoz <joaquin <at> tid.es> a
>> écrit :
>>>
>>> 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.
>>
>> That's nice!
>
> Ah, you should add a move ctor and assignment operator for better
> performance. Revised example:
>
> http://coliru.stacked-crooked.com/a/2ab8d00da3f71c84

Great :) Finally, the free-lunch is not over, I should just let
time pass and have my implementation improve all by itself :)

>> Do you have any gut feeling about whether there should be only
>> a single Exp-level hash-consing, or something with one flyweight
>> per AST type (and conversions). I'm still considering both.
>
> 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>();

works. Which also means that I need variations around
std::dynamic_pointer_cast etc., but it might be worth it. I
have experimentations on this on my real project, but it does
not work. I'll try to do that in the case of the simple toy
hierarchy you and I used so far.

>> You lost me here, I have no idea what special trick in std::optional
>> would prevent Flyweight from completing its forwarding to such
>> operators.
>
> It is a basic difference in indirection handling. Let me explain:
> std::optional<T> defines operator-> as
>
> optional<T> --> const T*
>
> which, for the case of optional<ptr<T>> (ptr being some pointer-like
> type), yields
>
> optional<ptr<T>> --> const ptr<T>*
>
> For instance:
>
> optional<T*> --> const T**
>
> With the interface you propose for flyweight, we'd have operator->
> for flyweight<ptr<T>> defined as
>
> optional<ptr<T>> --> const T*
>
> 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.

> 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.

> If I were to decided, I'd go for pointer semantics, which is more
> generally applicable. On the other hand, you can have your own
> poly_flyweight<T> class like the one shown with pointer semantics
> (because the intermediate pointer indirection is hidden in the
> implementation). Not sure I made myself clear :-)

Actually it's precisely because it forwards the operator-> call
to the wrapped that I see this as pass-thru. The operator->
and operator* behaves as if I were talking to the shared_ptr,
not to the flyweight.

But maybe I misunderstood what you meant here.


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net