lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lmi] Non-null smart pointer


From: Vadim Zeitlin
Subject: Re: [lmi] Non-null smart pointer
Date: Sun, 14 Oct 2018 00:54:34 +0200

On Sat, 13 Oct 2018 22:08:48 +0000 Greg Chicares <address@hidden> wrote:

GC> Does lmi need exactly one kind of smart pointer, or more than one?

 Right now I can't point to any precise place where we need either
shared_ptr<> or scoped_ptr<> or even unique_ptr<> which can be null. But
this doesn't mean there any no such places.

GC> Do all our smart pointers need to be returnable from a function,
GC> or only some of them? Do any actually need reference counting?

 I can try to find the definitive answers to these questions, but it's
going to take some time and, to be honest, I'm not sure why are they
important. What matters, IMO, is that we want to have a never null owning
smart pointer which can be returned from a function and that right now we
don't have such a thing.

GC> I find this casual measurement surprising:
GC> 
GC> /opt/lmi/src/lmi[0]$grep unique_ptr *.?pp |wc -l  
GC> 31
GC> /opt/lmi/src/lmi[0]$grep shared_ptr *.?pp |wc -l  
GC> 135

 Yes, I agree that this is suspicious.

GC> If we sort all of lmi's smart pointers into buckets, I'm not
GC> sure how many buckets we'd need, but I'm pretty sure that
GC> the "no smart pointer needed at all" bucket is nonempty,

 Yes, all pointers used by/passed to wxWidgets, for example, would fall in
this bucket. I've experimented with defining a gui_ptr<> template for such
pointers in some of my other programs, but I'm not really sure if it really
helps that much. In lmi it might be perhaps more useful because it could
provide a perfectly-forwarding ctor that would always use the right ("wx")
operator new for allocating the object. In any case, such gui_ptr<> is not
really a smart pointer, even if it looks like one, because it doesn't do
anything in its dtor.

GC> and I imagine that the "reference counting needed" bucket is relatively
GC> small if not quite empty.

 I guess so...


GC> pdf_writer_wx.cpp: wxPdfDocument* const pdf_doc = pdf_dc_.GetPdfDocument();
GC> 
GC> >  Yes, this would presumably become "not_null<wxPdfDocument*> whatever" and
GC> > you'd have to use get() to retrieve the raw pointer. OTOH, as it is not
GC> > supposed to be null, we shouldn't even need to use the pointer, only the
GC> > reference, and this can be obtained via operator*(), just as with the raw
GC> > pointer, so there would be no syntactic overhead.
GC> 
GC> void pdf_writer_wx::output_image
GC> ...
GC>     // Use wxPdfDocument API directly as wxDC doesn't provide a way to
GC>     // set the image scale at PDF level and also because passing via
GC>     // wxDC wastefully converts wxImage to wxBitmap only to convert it
GC>     // back to wxImage when embedding it into the PDF.
GC>     wxPdfDocument* const pdf_doc = pdf_dc_.GetPdfDocument();
GC>     LMI_ASSERT(pdf_doc);
GC> 
GC>     pdf_doc->SetImageScale(scale);
GC>     pdf_doc->Image(image_name, image, x, pos_y);
GC>     pdf_doc->SetImageScale(1);
GC> 
GC> That pointer needn't be copyable, moveable, or reference counted;
GC> it doesn't even need ownership, so maybe something like this
GC> 
GC>   http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3840.pdf
GC>   "A Proposal for the World’s Dumbest Smart Pointer"
GC> 
GC> would be appropriate--of course, with non-null-ness added. The benefit
GC> of using that almost everywhere, and raw pointers almost nowhere, is
GC> that we can't forget to write an assertion, because it's done implicitly.

 But isn't this exactly what not_null<T*> is?

GC> > GC> (I should think we'd automate dereferencing by defining operator.()
GC> > GC> and operator->(), but if we want to pass a pointer (say, to pass a
GC> > GC> wxWindow* to a wx function), then we'd need get() each time, or,
GC> > GC> equivalently, operator()()).
GC> > 
GC> >  wxWidgets is problematic because it requires passing pointers everywhere
GC> > and while in most places these pointers must be non-null, sometimes they
GC> > may be null. I'm afraid there is no good solution here, other than
GC> > providing a better API.
GC> 
GC> We aren't going to reimplement the wxWidgets API this decade, but we
GC> could make changes like this:
GC> 
GC> +    nonnull_ptr<wxPdfDocument> const pdf_doc = pdf_dc_.GetPdfDocument();
GC> -    wxPdfDocument* const pdf_doc = pdf_dc_.GetPdfDocument();
GC> -    LMI_ASSERT(pdf_doc);
GC> 
GC>      pdf_doc->SetImageScale(scale);
GC>      pdf_doc->Image(image_name, image, x, pos_y);
GC>      pdf_doc->SetImageScale(1);
GC> 
GC> where the last three lines require no change.

 Yes.


 So, what's the current state of discussion? Do we decide that we

1. Want to use not_null<T*>? And, if so, do we want to take some existing
   implementation or write our own version (which should be simple enough
   but OTOH why reinvent even a simple wheel?)?

2. Want to use not_null_unique_ptr<T*> which would be used for returning 
   new objects from functions?

3. Or need more time to review all the existing (smart) pointer usage in
   lmi before making the decision?


 Thanks,
VZ


reply via email to

[Prev in Thread] Current Thread [Next in Thread]