Boost logo

Boost Users :

Subject: Re: [Boost-users] Flyweight: wrapping shared_ptr
From: Joaquin M Lopez Munoz (joaquin_at_[hidden])
Date: 2014-10-08 08:32:01


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

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

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

Joaquín M López Muñoz
Telefónica


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