220 28016 <CAE7XuEXEV=xKW_g-1h1MFbg-3Fya83xkcoqGePvPbBPMTXPamA@mail.gmail.com> article
Path: news.gmane.org!.POSTED!not-for-mail
From: Nicolas Capens <nicolas.capens@gmail.com>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: Specifier to cause the destructor to be called at
 last use instead of end of scope
Date: Mon, 29 Aug 2016 15:22:30 +0000
Lines: 429
Approved: news@gmane.org
Message-ID: <CAE7XuEXEV=xKW_g-1h1MFbg-3Fya83xkcoqGePvPbBPMTXPamA@mail.gmail.com>
References: <ec2e95cc-3ef0-435b-aaf9-13e982c4583e@isocpp.org>
 <CANh8DEm-3RG1u99c6dUqSgthiVR_wE6FOfzHGbKuMqZBDptcOg@mail.gmail.com>
 <db0b8dd4-5cd9-4d4d-b7a8-95d6ab15ad8c@isocpp.org> <4387866d-169e-44a8-a858-d9aa96d54680@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: blaine.gmane.org
Mime-Version: 1.0
Content-Type: multipart/alternative; boundary=94eb2c112468597c00053b376ff2
X-Trace: blaine.gmane.org 1472484170 23726 195.159.176.226 (29 Aug 2016 15:22:50 GMT)
X-Complaints-To: usenet@blaine.gmane.org
NNTP-Posting-Date: Mon, 29 Aug 2016 15:22:50 +0000 (UTC)
Cc: "ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>, Matt Calabrese <calabrese@x.team>
To: Nicol Bolas <jmckesson@gmail.com>
Original-X-From: std-proposals+bncBC6MN3XGLYIMDJURXYCRUBFXNUXSK@isocpp.org Mon Aug 29 17:22:45 2016
Return-path: <std-proposals+bncBC6MN3XGLYIMDJURXYCRUBFXNUXSK@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-ua0-f198.google.com ([209.85.217.198])
	by blaine.gmane.org with esmtp (Exim 4.84_2)
	(envelope-from <std-proposals+bncBC6MN3XGLYIMDJURXYCRUBFXNUXSK@isocpp.org>)
	id 1beOOX-0005Cq-7K
	for gclcip-std-proposals@m.gmane.org; Mon, 29 Aug 2016 17:22:41 +0200
Original-Received: by mail-ua0-f198.google.com with SMTP id j4sf205941331uaj.2
        for <gclcip-std-proposals@m.gmane.org>; Mon, 29 Aug 2016 08:22:42 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=isocpp-org.20150623.gappssmtp.com; s=20150623;
        h=mime-version:references:in-reply-to:from:date:message-id:subject:to
         :cc:x-original-sender:x-original-authentication-results:reply-to
         :precedence:mailing-list:list-id:x-spam-checked-in-group:list-post
         :list-help:list-archive:list-subscribe:list-unsubscribe;
        bh=aP1IM2ajed+1xmvPvv/A/EmkpY/BCVtgBTyS546+tmY=;
        b=r4IBv0A3HGMroDv+X+4HhQS06r6RNg9NOzCZeq1X/IoKTD+SoR/uehIx5K/JMkVrDY
         BmohohXfiAX4atHw8EjznjfQAmCR0/Y5uGW5cUrnuknjnxW1aGPOSOXQ6rPHd3+CY/TU
         i/mqKAIT/e30WGyo41dtO6IR0JuYyXSfp9AqcnqU/MHwAMdNu+ZA0wiOPEgxkTLN2+WJ
         xdn6Ex3qea0tyx+VrcktNFASbLVRfYA5nNhW3l3VXb3BDCQm4CPEgG2vErV5Xh3c4g5W
         rP+eD/VLAQsMAQbJmdKHYQA+TTVtFJhNDio86fy+XMzIgZiaGB9xInKdZBkHzpIJsT29
         nODw==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20130820;
        h=x-gm-message-state:mime-version:references:in-reply-to:from:date
         :message-id:subject:to:cc:x-original-sender
         :x-original-authentication-results:reply-to:precedence:mailing-list
         :list-id:x-spam-checked-in-group:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe;
        bh=aP1IM2ajed+1xmvPvv/A/EmkpY/BCVtgBTyS546+tmY=;
        b=U3QgzY5/URRhgPIPWeAhmnhNYS/Z3H/66AIUzpm7rbR8oahghHOVoPcFdtnFj0ELVj
         WliOngkLamZJ6nOy1cCVaddgSDY0bOsyOPEGAbRasRPg7n9spMSNZKe+Ttp3498WldGZ
         G2oZOp2mf4FnXaHcSiGTnoZ1SyiMSmG9d1CYTaT52N2p0y8HtmGrEFH6yFqeCKQ8S3Vi
         Oi+h6vpKllNczEITiGHA80yDXNGVRG00TVq6DqVgvi/CqgY5UnhBk495d0I3ZQdrkg2A
         nLGCVLqa7XFXoJewnQczKI1qzdyF6RVG720qT6/BQ7lggWOlIhhvKVBw1W9nvG3ywuU/
         WXGQ==
X-Gm-Message-State: AE9vXwNz6XYhUfJLmN6CoVwQgw6c538FKtTH5xMFHXklvqH4Amt6r7Rn58sI8OGtmGpBwQ==
X-Received: by 10.129.157.76 with SMTP id u73mr13665478ywg.16.1472484161987;
        Mon, 29 Aug 2016 08:22:41 -0700 (PDT)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.157.48.18 with SMTP id d18ls7952804otc.13.gmail; Mon, 29 Aug
 2016 08:22:41 -0700 (PDT)
X-Received: by 10.55.71.201 with SMTP id u192mr20162604qka.100.1472484161180;
        Mon, 29 Aug 2016 08:22:41 -0700 (PDT)
Original-Received: from mail-qk0-x22c.google.com (mail-qk0-x22c.google.com. [2607:f8b0:400d:c09::22c])
        by mx.google.com with ESMTPS id y32si23567311qty.139.2016.08.29.08.22.41
        for <std-proposals@isocpp.org>
        (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
        Mon, 29 Aug 2016 08:22:41 -0700 (PDT)
Received-SPF: pass (google.com: domain of nicolas.capens@gmail.com designates 2607:f8b0:400d:c09::22c as permitted sender) client-ip=2607:f8b0:400d:c09::22c;
Original-Received: by mail-qk0-x22c.google.com with SMTP id z190so141087972qkc.0
        for <std-proposals@isocpp.org>; Mon, 29 Aug 2016 08:22:41 -0700 (PDT)
X-Received: by 10.233.232.195 with SMTP id a186mr19119792qkg.109.1472484160927;
 Mon, 29 Aug 2016 08:22:40 -0700 (PDT)
In-Reply-To: <4387866d-169e-44a8-a858-d9aa96d54680@isocpp.org>
X-Original-Sender: Nicolas.Capens@gmail.com
X-Original-Authentication-Results: mx.google.com;       dkim=pass
 header.i=@gmail.com;       spf=pass (google.com: domain of
 nicolas.capens@gmail.com designates 2607:f8b0:400d:c09::22c as permitted
 sender) smtp.mailfrom=nicolas.capens@gmail.com;       dmarc=pass (p=NONE
 dis=NONE) header.from=gmail.com
Precedence: list
Mailing-list: list std-proposals@isocpp.org; contact std-proposals+owners@isocpp.org
List-ID: <std-proposals.isocpp.org>
X-Google-Group-Id: 399137483710
List-Post: <https://groups.google.com/a/isocpp.org/group/std-proposals/post>, <mailto:std-proposals@isocpp.org>
List-Help: <https://support.google.com/a/isocpp.org/bin/topic.py?topic=25838>, <mailto:std-proposals+help@isocpp.org>
List-Archive: <https://groups.google.com/a/isocpp.org/group/std-proposals/>
List-Subscribe: <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>,
 <mailto:std-proposals+subscribe@isocpp.org>
List-Unsubscribe: <mailto:googlegroups-manage+399137483710+unsubscribe@googlegroups.com>,
 <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:28016
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/28016>

--94eb2c112468597c00053b376ff2
Content-Type: text/plain; charset=UTF-8

On Wed, Aug 24, 2016 at 6:05 PM, Nicol Bolas <jmckesson@gmail.com> wrote:

> On Wednesday, August 24, 2016 at 5:17:26 PM UTC-4, nicolas...@gmail.com
> wrote:
>>
>> On Wednesday, August 24, 2016 at 3:19:24 PM UTC-4, Matt Calabrese wrote:
>>>
>>> On Wed, Aug 24, 2016 at 11:51 AM, <nicolas...@gmail.com> wrote:
>>>
>>>> Hi all,
>>>>
>>>> I'd like to propose a new kind of destructor that gets called after a
>>>> local object's last use, instead of at the end of its scope.
>>>>
>>>> The use of this would be to free resources held by the object sooner.
>>>> This could be heap memory, file handles, mutex locks, etc. Releasing them
>>>> as soon as we're done with the object that represents them would result in
>>>> more efficient programs.
>>>>
>>>> Currently such optimization can only be achieved by explicitly
>>>> releasing the resources, which is inconvenient, bug prone, and reduces
>>>> readability. Limiting the scope with extra braces or by putting the
>>>> operations in a subroutine also often isn't a desirable workaround. Note
>>>> that compilers have been doing liveness analysis for register allocation
>>>> and stack compaction for a very long time and we take these optimizations
>>>> for granted. I'd like to see it get extended to heap memory and other
>>>> resources as well.
>>>>
>>>> The syntax for this could be an annotation of the destructor
>>>> declaration with a keyword, symbol, or attribute. For example, "auto
>>>> ~Object();", "volatile ~Object();", "~~Object();", or "[[eager]]
>>>> ~Object();".
>>>>
>>>> Thoughts?
>>>>
>>>
>>> While I would like C++ to eventually get a way to do the equivalent of
>>> this in some form (more generally, I want destructive move, which is
>>> related to this even though it may not be immediately obvious),
>>>
>>
>> Yes, a destructive assignment could count as a last use of its previous
>> value and call the destructor that I'm proposing. I'd also like it to be
>> called after the last use as a source argument too though.
>>
>>
>>> I do not think that the appropriate place to notate the premature
>>> destruction is on the destructor declaration. Instead, I believe it needs
>>> to be explicit at the usage-site. This is primarily because we are in a
>>> language where side-effects matter.
>>>
>>
>> I wouldn't call it premature destruction. Eager instead of today's lazy
>> destruction at the end of the scope, seems like a better description to me.
>>
>
> Playing word games doesn't change the fact that the standard makes it
> clear that destruction of an automatic object happens in a single,
> well-defined place. Your proposal wants to *transparently* change that
> location based on something in the type of that object.
>

It's not a word game. Premature anything is a bad thing and we shouldn't
present this feature to users that way. Lazy vs. eager is more neutral.
Other suggestions welcome.

Anyway, making the destruction happen in a single, well-defined place can
be done by using the last "local" use of the object. It's also the most bug
prone, but if determinism is a necessity, then this is a feasible starting
point. It's not clear to me though that determinism is necessary. We don't
ask compilers to free up registers in a determinable way either. Anywhere
between the last conservative use and the end of the scope is valid. For my
use cases of eager destruction that's acceptable as well. I'd just like
make sure that compilers aren't going to be overly conservative.


> The ability to execute the destructor and simultaneously prevent the
> compiler from doing so is something that can be discussed and debated. But
> as Matt said, it would be explicit at the point of use, not implicitly
> built into the type. The code that wants to change the default behavior,
> which is the code that gains certain responsibilities by doing so, is the
> code *using* the object, not the code *defining* it.
>

First of all, that doesn't solve my use cases
<https://groups.google.com/a/isocpp.org/forum/#!msg/std-proposals/IUxA4cx8yHc/yKNqKl8hDgAJ>.
And secondly I can already do that today using a method to free up the
resources held by the object and being careful that the destructor doesn't
attempt to free them again. If there's still value in your feature that I
might be missing, fine, feel free to discuss it elsewhere.


> Putting it in the type is simply the wrong place for it. It's the code
> that needs the optimization who should be responsible for invoking this
> behavior.
>
> Anyway, for the use cases that I envision, the annotation at destructor
>> declaration is appropriate. For example say I need a huge matrix to
>> temporarily store some intermediate results. I could use "double
>> matrix[10000][10000];" and rely on the compiler's optimizations to use the
>> memory for other purposes as soon as I'm done with this matrix. But it's
>> simply not going to fit on the stack. So instead I'll use an object with a
>> pointer to heap memory. But now it only gets freed when it goes out of
>> scope.
>>
>
> No, it gets freed when you want it to be freed. Observe:
>
> auto heap_allocation = std::make_unique<T>(...);
>
> //use the object
>
> heap_allocation.reset();
>
> See? it's been freed after the last use.
>
> This way, you don't have to play games of wondering exactly when the
> allocation is destroyed. It's destroyed when you *destroy it*.
>

I don't want to manually destroy it. That's a critical part of the feature
I'm proposing. It needs to call the destructor automatically, just like
today for local objects, but call it more eagerly than at the end of the
scope so we get some optimization benefits without programmer involvement.
The only room for debate is whether we aggressively call the destructor at
the last local use, or require it to be conservative, or something in
between.


> You can explicitly reset smart pointers; you can explicitly close streams.
> And for moveable types that don't offer such features, Magnus gave a great
> answer:
>
> Object(std::move(auto_val));
>
> That works for pretty much any moveable `Object` type that represents a
> resource.
>
> The point in time when an automatic variable is destroyed should not be a
> *mystery*. It should never be in question when an automatic variable is
> no longer a legitimate object.
>

Why? We don't question whether a register is still in use or not, don't we?
There are some objects, some, not all of them, that could be treated to be
self-contained just like a register so that the compiler is free to
optimize their lifetime to something shorter than their scope.


> So I want to make it clear to the compiler that I'd like it to be
>> destroyed eagerly, and not just for this one but for every instance. It's a
>> property of the class itself that I want it's destructor to be called
>> eagerly. If I don't want that behavior I can simply use an equivalent class
>> without eager destructor.
>>
>
> You've provided a very good reason not to do this at all. We do not want
> to encourage the proliferation of types that differ *only* by the
> presence or absence of "eager destruction". We don't want
> `eager_unique_ptr` or `eager_ifstream` or `eager_vector` or whatever.
>

The way I envision this to be used you won't need such a prefix at all. It
would just be Matrix, Int, or Streamer, like in my examples
<https://groups.google.com/a/isocpp.org/forum/#!msg/std-proposals/IUxA4cx8yHc/yKNqKl8hDgAJ>.
The framework they're part of is responsible of making sure they're
self-contained objects and under normal circumstances can't be used
incorrectly.


> Even with that, you might think that it's okay to annotate types that
>>> contain no logical relationships to objects that it does not own. For
>>> instance, something that just contains an int or a unique_ptr to some
>>> object with no relationships, etc. The problem is, even in these cases,
>>> there is nothing stopping some *other* object from storing a pointer or
>>> reference to an instance of your
>>> automatically-prematurely-destructible-type. If someone *does* hold such a
>>> reference and your annotated type is "no longer used", then the object that
>>> refers to it will now have a dangling reference. Point being, your
>>> annotation cannot be at the type level.
>>>
>>
>> This issue is not very different from still having a reference to a local
>> variable after it has gone out of scope. C++ is inherently unsafe, and you
>> simply need to know what you're doing. With lazy destruction, don't use any
>> references to the object after it has gone out of scope. With eager
>> destruction, don't use any references to the object after its last use. A
>> compiler warning could help prevent people from shooting themselves in the
>> foot in both cases.
>>
>
> What would trigger such a warning? Passing a variable of such a type as a
> reference to someone else? Because that's all the compiler can know: that a
> reference or pointer was passed to some function. It has no idea if that
> function retains that value or not, or when it is expected to relinquish it.
>
> You'd need serious static analysis to avoid a litany of false positives.
>

Indeed. This is the kind of information that will determine whether we can
go with the conservative option or need the more aggressive one. But I'm
not fully convinced that this analysis is hard to do. The equivalent
problem for registers is called interprocedural register allocation, and I
was able to find research papers on it dating back to the early 80's. And
knowing whether a function retained a reference is in fact easier than
knowing which registers it uses.

-- 
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAE7XuEXEV%3DxKW_g-1h1MFbg-3Fya83xkcoqGePvPbBPMTXPamA%40mail.gmail.com.

--94eb2c112468597c00053b376ff2
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On W=
ed, Aug 24, 2016 at 6:05 PM, Nicol Bolas <span dir=3D"ltr">&lt;<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>&gt;</s=
pan> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex=
;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span>On Wed=
nesday, August 24, 2016 at 5:17:26 PM UTC-4, <a href=3D"mailto:nicolas...@g=
mail.com" target=3D"_blank">nicolas...@gmail.com</a> wrote:<blockquote clas=
s=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div dir=3D"ltr">On Wednesday, August 24, 2016 at 3=
:19:24 PM UTC-4, Matt Calabrese wrote:<blockquote class=3D"gmail_quote" sty=
le=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1e=
x"><div dir=3D"ltr"><div><div class=3D"gmail_quote">On Wed, Aug 24, 2016 at=
 11:51 AM,  <span dir=3D"ltr">&lt;<a rel=3D"nofollow">nicolas...@gmail.com<=
/a>&gt;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:=
0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><d=
iv>Hi all,</div><div><br></div>I&#39;d like to propose a new kind of destru=
ctor that gets called after a local object&#39;s last use, instead of at th=
e end of its scope.<div><br></div><div>The use of this would be to free res=
ources held by the object sooner. This could be heap memory, file handles, =
mutex locks, etc. Releasing them as soon as we&#39;re done with the object =
that represents them would result in more efficient programs.</div><div><br=
></div><div>Currently such optimization can only be achieved by explicitly =
releasing the resources, which is inconvenient, bug prone, and reduces read=
ability. Limiting the scope with extra braces or by putting the operations =
in a subroutine also often isn&#39;t a desirable workaround. Note that comp=
ilers have been doing liveness analysis for register allocation and stack c=
ompaction for a very long time and we take these optimizations for granted.=
 I&#39;d like to see it get extended to heap memory and other resources as =
well.</div><div><span style=3D"line-height:17px"><br></span></div><div>The =
s<span style=3D"line-height:17px">yntax for this could be an annotation of =
the destructor declaration with a keyword, symbol, or attribute. For exampl=
e, &quot;auto ~Object();&quot;, &quot;volatile ~Object();&quot;, &quot;~~Ob=
ject();&quot;, or &quot;[[eager]] ~Object();&quot;.</span></div><div><span =
style=3D"line-height:17px"><br></span></div><div><span style=3D"line-height=
:17px">Thoughts?</span></div></div></blockquote><div><br></div><div>While I=
 would like C++ to eventually get a way to do the equivalent of this in som=
e form (more generally, I want destructive move, which is related to this e=
ven though it may not be immediately obvious),</div></div></div></div></blo=
ckquote><div><br></div><div>Yes, a destructive assignment could count as a =
last use of its previous value and call the destructor that I&#39;m proposi=
ng. I&#39;d also like it to be called after the last use as a source argume=
nt too though.</div><div>=C2=A0</div><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex=
"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>I do not think that=
 the appropriate place to notate the premature destruction is on the destru=
ctor declaration. Instead, I believe it needs to be explicit at the usage-s=
ite. This is primarily because we are in a language where side-effects matt=
er.</div></div></div></div></blockquote><div><br></div><div>I wouldn&#39;t =
call it premature destruction. Eager instead of today&#39;s lazy destructio=
n at the end of the scope, seems like a better description to me.</div></di=
v></blockquote></span><div><br>Playing word games doesn&#39;t change the fa=
ct that the standard makes it clear that destruction of an automatic object=
 happens in a single, well-defined place. Your proposal wants to *transpare=
ntly* change that location based on something in the type of that object.<b=
r></div></div></blockquote><div><br></div></div></div><div dir=3D"ltr"><div=
 class=3D"gmail_extra"><div class=3D"gmail_quote"><div>It&#39;s not a word =
game. Premature anything is a bad thing and we shouldn&#39;t present this f=
eature to users that way. Lazy vs. eager is more neutral. Other suggestions=
 welcome.</div><div><br></div><div>Anyway, making the destruction happen in=
 a single, well-defined place can be done by using the last &quot;local&quo=
t; use of the object. It&#39;s also the most bug prone, but if determinism =
is a necessity, then this is a feasible starting point. It&#39;s not clear =
to me though that determinism is necessary. We don&#39;t ask compilers to f=
ree up registers in a determinable way either. Anywhere between the last co=
nservative use and the end of the scope is valid. For my use cases of eager=
 destruction that&#39;s acceptable as well. I&#39;d just like make sure tha=
t compilers aren&#39;t going to be overly conservative.</div></div></div></=
div><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">=
<div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>The a=
bility to execute the destructor and simultaneously prevent the compiler fr=
om doing so is something that can be discussed and debated. But as Matt sai=
d, it would be explicit at the point of use, not implicitly built into the =
type. The code that wants to change the default behavior, which is the code=
 that gains certain responsibilities by doing so, is the code <i>using</i> =
the object, not the code <i>defining</i> it.<br></div></div></blockquote><d=
iv><br></div><div>First of all, that doesn&#39;t solve <a href=3D"https://g=
roups.google.com/a/isocpp.org/forum/#!msg/std-proposals/IUxA4cx8yHc/yKNqKl8=
hDgAJ">my use cases</a>. And secondly I can already do that today using a m=
ethod to free up the resources held by the object and being careful that th=
e destructor doesn&#39;t attempt to free them again. If there&#39;s still v=
alue in your feature that I might be missing, fine, feel free to discuss it=
 elsewhere.</div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=
=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><div>Putting it in the type is simply the wrong place for it. It&#=
39;s the code that needs the optimization who should be responsible for inv=
oking this behavior.<br><br></div><span><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:=
1ex"><div dir=3D"ltr"><div></div><div>Anyway, for the use cases that I envi=
sion, the annotation at destructor declaration is appropriate. For example =
say I need a huge matrix to temporarily store some intermediate results. I =
could use &quot;double matrix[10000][10000];&quot; and rely on the compiler=
&#39;s optimizations to use the memory for other purposes as soon as I&#39;=
m done with this matrix. But it&#39;s simply not going to fit on the stack.=
 So instead I&#39;ll use an object with a pointer to heap memory. But now i=
t only gets freed when it goes out of scope.</div></div></blockquote></span=
><div><br>No, it gets freed when you want it to be freed. Observe:<br><br><=
div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187=
);border-style:solid;border-width:1px;word-wrap:break-word"><code><div><spa=
n style=3D"color:#008">auto</span><span style=3D"color:#000"> heap_allocati=
on </span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> =
std</span><span style=3D"color:#660">::</span><span style=3D"color:#000">ma=
ke_unique</span><span style=3D"color:#660">&lt;</span><span style=3D"color:=
#000">T</span><span style=3D"color:#660">&gt;(...);</span><span style=3D"co=
lor:#000"><br><br></span><span style=3D"color:#800">//use the object</span>=
<span style=3D"color:#000"><br><br>heap_allocation</span><span style=3D"col=
or:#660">.</span><span style=3D"color:#000">reset</span><span style=3D"colo=
r:#660">();</span></div></code></div><br>See? it&#39;s been freed after the=
 last use.<br><br>This way, you don&#39;t have to play games of wondering e=
xactly when the allocation is destroyed. It&#39;s destroyed when you <i>des=
troy it</i>.<br></div></div></blockquote><div><br></div><div>I don&#39;t wa=
nt to manually destroy it. That&#39;s a critical part of the feature I&#39;=
m proposing. It needs to call the destructor automatically, just like today=
 for local objects, but call it more eagerly than at the end of the scope s=
o we get some optimization benefits without programmer involvement. The onl=
y room for debate is whether we aggressively call the destructor at the las=
t local use, or require it to be conservative, or something in between.</di=
v><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 =
..8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>You=
 can explicitly reset smart pointers; you can explicitly close streams. And=
 for moveable types that don&#39;t offer such features, Magnus gave a great=
 answer:<br><br><div style=3D"background-color:rgb(250,250,250);border-colo=
r:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:break-word=
"><code><div><span style=3D"color:#606">Object</span><span style=3D"color:#=
660">(</span><span style=3D"color:#000">std</span><span style=3D"color:#660=
">::</span><span style=3D"color:#000">move</span><span style=3D"color:#660"=
>(</span><span style=3D"color:#000">auto_val</span><span style=3D"color:#66=
0">));</span></div></code></div><br>That works for pretty much any moveable=
 `Object` type that represents a resource.<br><br>The point in time when an=
 automatic variable is destroyed should not be a <i>mystery</i>. It should =
never be in question when an automatic variable is no longer a legitimate o=
bject.<br></div></div></blockquote><div><br></div><div>Why? We don&#39;t qu=
estion whether a register is still in use or not, don&#39;t we? There are s=
ome objects, some, not all of them, that could be treated to be self-contai=
ned just like a register so that the compiler is free to optimize their lif=
etime to something shorter than their scope.</div><div>=C2=A0</div><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><div></div><span><blockquote class=
=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><div>So I want to make it clear to =
the compiler that I&#39;d like it to be destroyed eagerly, and not just for=
 this one but for every instance. It&#39;s a property of the class itself t=
hat I want it&#39;s destructor to be called eagerly. If I don&#39;t want th=
at behavior I can simply use an equivalent class without eager destructor.<=
/div></div></blockquote></span><div><br>You&#39;ve provided a very good rea=
son not to do this at all. We do not want to encourage the proliferation of=
 types that differ <i>only</i> by the presence or absence of &quot;eager de=
struction&quot;. We don&#39;t want `eager_unique_ptr` or `eager_ifstream` o=
r `eager_vector` or whatever.<br></div></div></blockquote><div><br></div><d=
iv>The way I envision this to be used you won&#39;t need such a prefix at a=
ll. It would just be Matrix, Int, or Streamer, like in <a href=3D"https://g=
roups.google.com/a/isocpp.org/forum/#!msg/std-proposals/IUxA4cx8yHc/yKNqKl8=
hDgAJ">my examples</a>. The framework they&#39;re part of is responsible of=
 making sure they&#39;re self-contained objects and under normal circumstan=
ces can&#39;t be used incorrectly.</div><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padd=
ing-left:1ex"><div dir=3D"ltr"><div></div><span><blockquote class=3D"gmail_=
quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddi=
ng-left:1ex"><div dir=3D"ltr"><div> </div><blockquote class=3D"gmail_quote"=
 style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-lef=
t:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>Even with that=
, you might think that it&#39;s okay to annotate types that contain no logi=
cal relationships to objects that it does not own. For instance, something =
that just contains an int or a unique_ptr to some object with no relationsh=
ips, etc. The problem is, even in these cases, there is nothing stopping so=
me *other* object from storing a pointer or reference to an instance of you=
r automatically-prematurely-destructible-type. If someone *does* hold such =
a reference and your annotated type is &quot;no longer used&quot;, then the=
 object that refers to it will now have a dangling reference. Point being, =
your annotation cannot be at the type level.</div></div></div></div></block=
quote><div><br></div><div>This issue is not very different from still havin=
g a reference to a local variable after it has gone out of scope. C++ is in=
herently unsafe, and you simply need to know what you&#39;re doing. With la=
zy destruction, don&#39;t use any references to the object after it has gon=
e out of scope. With eager destruction, don&#39;t use any references to the=
 object after its last use. A compiler warning could help prevent people fr=
om shooting themselves in the foot in both cases.</div></div></blockquote><=
/span><div dir=3D"ltr"><br>What would trigger such a warning? Passing a var=
iable of such a type as a reference to someone else? Because that&#39;s all=
 the compiler can know: that a reference or pointer was passed to some func=
tion. It has no idea if that function retains that value or not, or when it=
 is expected to relinquish it.<br><br>You&#39;d need serious static analysi=
s to avoid a litany of false positives.</div></div></blockquote><div><br></=
div><div>Indeed. This is the kind of information that will determine whethe=
r we can go with the conservative option or need the more aggressive one. B=
ut I&#39;m not fully convinced that this analysis is hard to do. The equiva=
lent problem for registers is called interprocedural register allocation, a=
nd I was able to find research papers on it dating back to the early 80&#39=
;s. And knowing whether a function retained a reference is in fact easier t=
han knowing which registers it uses.</div></div></div></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAE7XuEXEV%3DxKW_g-1h1MFbg-3Fya83xkco=
qGePvPbBPMTXPamA%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAE7XuEXEV%3DxK=
W_g-1h1MFbg-3Fya83xkcoqGePvPbBPMTXPamA%40mail.gmail.com</a>.<br />

--94eb2c112468597c00053b376ff2--

.
