lmi
[Top][All Lists]
Advanced

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

Re: [lmi] Reference lifetime extension


From: Vadim Zeitlin
Subject: Re: [lmi] Reference lifetime extension
Date: Fri, 12 Oct 2018 01:58:53 +0200

On Thu, 11 Oct 2018 23:29:12 +0000 Greg Chicares <address@hidden> wrote:

GC> On 10/11/18 8:55 PM, Vadim Zeitlin wrote:
[...]
GC> > but this operator doesn't return a temporary object, so rules about
GC> > extending its life-time don't apply at all.
GC> 
GC> It doesn't return a temporary?

 No, it returns a reference to a member of a temporary object, but this
member is not a temporary on its own.

 IOW, the returned temporary shared_ptr is a prvalue, but the result of
calling its operator*() is an lvalue.

GC> A temporary would be created [class.temporary/1.1]
GC> | when a prvalue is materialized so that it can be used as a glvalue

 This is the case for shared_ptr<> itself.

GC> and
GC> | Temporary objects are materialized:
GC> | (2.1) — when binding a reference to a prvalue

 But you don't bind a reference to it. You bind a reference to the result
of calling operator*() on it which is very different.

GC> I believe this line does bind a reference to something:
GC>   ledger_pdf_generator const& pdf = *ledger_pdf_generator::create();
GC> and therefore that "something", i.e. what shared_ptr::operator*()
GC> returns, must not be a prvalue...right? What then is its "value
GC> category" [basic.lval/1]?

 It's an lvalue.

GC> I was hoping I'd never have to learn this stuff.

 I won't pretend that all this ???value stuff is not confusing, I still
look up https://en.cppreference.com/w/cpp/language/value_category myself
regularly.

 But I still think that the original example is completely clear
intuitively: you just can't expect binding a reference to a member of
shared_ptr<> to extend the lifetime of the shared_ptr<> object itself
because a field of an object has no power over its owner lifetime. So
whatever you do with shared_ptr<>._M_ptr or whatever is called the field
whose value is returned by operator*(), the shared_ptr<> itself will still
be destroyed at the end of the statement and to prevent this from happening
you absolutely need to bind a (const) reference to this object itself.


GC> I've found a way to avoid it in this case, which I'll push presently.

 I regret this change. It seems much more natural to me to think of an
object capable of generating the PDF from the given inputs rather than of a
"PDF command". In particular, the former was much easier to extend if
necessary, as we could simply add another virtual method to it, and it
doesn't seem at all impossible to me that we could need it in the future.

 Also, there is a fact that the latest master doesn't work at all for me
when building with MSVS, but this is only an easy to fix typo, could you
please apply this patch to correct it?

---------------------------------- >8 --------------------------------------
diff --git a/main_wx.cpp b/main_wx.cpp
index 607fe331c..e0bb7ba54 100644
--- a/main_wx.cpp
+++ b/main_wx.cpp
@@ -46,7 +46,7 @@
 LMI_FORCE_LINKING_EX_SITU(alert_wx)
 LMI_FORCE_LINKING_EX_SITU(file_command_wx)
 LMI_FORCE_LINKING_EX_SITU(group_quote_pdf_generator_wx)
-LMI_FORCE_LINKING_IN_SITU(pdf_command_wx)
+LMI_FORCE_LINKING_EX_SITU(pdf_command_wx)
 LMI_FORCE_LINKING_EX_SITU(progress_meter_wx)
 LMI_FORCE_LINKING_EX_SITU(system_command_wx)
---------------------------------- >8 --------------------------------------
 
 I realize that chances of reverting this change are slim, but I really
think it's a huge overreaction to the initial problem. Getting rid of
shared_ptr<> is a good thing (and I admit that I have absolutely no idea
why had I used it here in the first place), but I would have preferred just
replacing it with unique_ptr<> instead of completely removing
ledger_pdf_generator class.

 Regards,
VZ


reply via email to

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