220 12606 <CAEWUs4jXt=vC1FM_Pw+ZdAqtFbSzP8hkJPRBJ-AkTXTu_GapVg@mail.gmail.com> article
Path: news.gmane.org!not-for-mail
From: Adi Shavit <adishavit@gmail.com>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: Questions about N3949 - Scoped Resource - Generic
 RAII Wrapper for the Standard Library
Date: Mon, 1 Sep 2014 09:55:04 +0300
Lines: 385
Approved: news@gmane.org
Message-ID: <CAEWUs4jXt=vC1FM_Pw+ZdAqtFbSzP8hkJPRBJ-AkTXTu_GapVg@mail.gmail.com>
References: <038222e0-66c3-4837-b158-e911dffb3c55@isocpp.org>
 <1DB1B82D-0067-4D01-A054-9113B6D7B3ED@gmail.com> <e706261e-f3e4-4c4d-9045-ab91be7161f3@isocpp.org>
 <CD1AAFB9-5458-4040-A34B-1A4A726B6928@gmail.com>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: plane.gmane.org
Mime-Version: 1.0
Content-Type: multipart/alternative; boundary=001a11c2ba8e5111670501fb7d9e
X-Trace: ger.gmane.org 1409554542 22764 80.91.229.3 (1 Sep 2014 06:55:42 GMT)
X-Complaints-To: usenet@ger.gmane.org
NNTP-Posting-Date: Mon, 1 Sep 2014 06:55:42 +0000 (UTC)
To: std-proposals@isocpp.org
Original-X-From: std-proposals+bncBDMLX45JSIJBBZ5QSCQAKGQERPXOZGQ@isocpp.org Mon Sep 01 08:55:36 2014
Return-path: <std-proposals+bncBDMLX45JSIJBBZ5QSCQAKGQERPXOZGQ@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-we0-f197.google.com ([74.125.82.197])
	by plane.gmane.org with esmtp (Exim 4.69)
	(envelope-from <std-proposals+bncBDMLX45JSIJBBZ5QSCQAKGQERPXOZGQ@isocpp.org>)
	id 1XOLWZ-0005RA-Rt
	for gclcip-std-proposals@m.gmane.org; Mon, 01 Sep 2014 08:55:35 +0200
Original-Received: by mail-we0-f197.google.com with SMTP id k48sf3211883wev.0
        for <gclcip-std-proposals@m.gmane.org>; Sun, 31 Aug 2014 23:55:35 -0700 (PDT)
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20130820;
        h=x-gm-message-state:mime-version:in-reply-to:references:from:date
         :message-id:subject:to:x-original-sender
         :x-original-authentication-results:reply-to:precedence:mailing-list
         :list-id:list-post:list-help:list-archive:list-subscribe
         :list-unsubscribe:content-type;
        bh=iCRk+lIGs1tM2l5ADma4S7REJN//BRysYyvfHv9URTI=;
        b=FvFovyh1LpUsQUjKK5XMdLvV7aYYnsBM2is3c2yw5D1NudtQwLWDUZ+K7IYlBRsrgU
         ac0YpV6bUBNu17DmtHE6j8AkDNP33h8K2qaI7DUNCPPxWTLAb4n3YMK3PvsKVAVKRGrT
         a+foiv32NThIY+qMvKhcMAnunDi06xN9AAP5eD+LOm/ot8ptaPNOxz4St3Hh/ImPlX8C
         dy4TkrdGamI0Dt1cCwjpkaCKwffXE53Ep6Pt4A8QTr90MYsrUSkDHoEWR+rZubDEj8rB
         OzLbRELUGDZb9dfTfAXOeww7eRPZLMTcAdPJAINOUhSP1wsXKPlZCAkbM/AQYZJhJCJZ
         x0yQ==
X-Gm-Message-State: ALoCoQmo/q1V1X7LwL3uvUEUaC+YgjiU/1du2sJApbbLSKpU64US4FEwlBEwECNuJgCjfKisS8OZ
X-Received: by 10.194.173.1 with SMTP id bg1mr2309750wjc.1.1409554535545;
        Sun, 31 Aug 2014 23:55:35 -0700 (PDT)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.180.104.228 with SMTP id gh4ls366886wib.19.canary; Sun, 31 Aug
 2014 23:55:34 -0700 (PDT)
X-Received: by 10.180.75.144 with SMTP id c16mr20003421wiw.9.1409554534729;
        Sun, 31 Aug 2014 23:55:34 -0700 (PDT)
Original-Received: from mail-wg0-x231.google.com (mail-wg0-x231.google.com [2a00:1450:400c:c00::231])
        by mx.google.com with ESMTPS id gm4si8536361wib.2.2014.08.31.23.55.34
        for <std-proposals@isocpp.org>
        (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128);
        Sun, 31 Aug 2014 23:55:34 -0700 (PDT)
Received-SPF: pass (google.com: domain of adishavit@gmail.com designates 2a00:1450:400c:c00::231 as permitted sender) client-ip=2a00:1450:400c:c00::231;
Original-Received: by mail-wg0-f49.google.com with SMTP id y10so4940896wgg.32
        for <std-proposals@isocpp.org>; Sun, 31 Aug 2014 23:55:34 -0700 (PDT)
X-Received: by 10.180.9.226 with SMTP id d2mr19163495wib.81.1409554534435;
 Sun, 31 Aug 2014 23:55:34 -0700 (PDT)
Original-Received: by 10.194.152.131 with HTTP; Sun, 31 Aug 2014 23:55:04 -0700 (PDT)
In-Reply-To: <CD1AAFB9-5458-4040-A34B-1A4A726B6928@gmail.com>
X-Original-Sender: adishavit@gmail.com
X-Original-Authentication-Results: mx.google.com;       spf=pass (google.com:
 domain of adishavit@gmail.com designates 2a00:1450:400c:c00::231 as permitted
 sender) smtp.mail=adishavit@gmail.com;       dkim=pass header.i=@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: <http://groups.google.com/a/isocpp.org/group/std-proposals/post>, <mailto:std-proposals@isocpp.org>
List-Help: <http://support.google.com/a/isocpp.org/bin/topic.py?topic=25838>, <mailto:std-proposals+help@isocpp.org>
List-Archive: <http://groups.google.com/a/isocpp.org/group/std-proposals/>
List-Subscribe: <http://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>,
 <http://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:12606
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/12606>

--001a11c2ba8e5111670501fb7d9e
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

Hi David,

  Thank you for the detailed explanation and the sample code.
Assuming we want/need to write new small classes, your approach, indeed,
reduces the amount of boilerplate and error-prone code and makes good use
of unique_ptr.

Ultimately, I think that it is a question of style, taste and context,
whether to write small (efficient) wrappers or try to use a generic wrapper
(which amounts to about one extra line of user code if at all). As you
mention, your suggestion is really an alternative to the classes proposed
in this proposal and is always a valid option regardless if this proposal
makes it into the standard or not.

I think that if your generalize and genericise the code in your example,
you will essentially get a version of scoped_resource sans virtual calls,
and possibly sans deleter type in type - which is basically what I wanted.

Since this discussion is in the context of the proposal itself (and more
generally, its applicability to common use cases), I think your suggestion
is important for understanding alternatives to common use cases and any
pros and cons each option has. It does not directly answer my original
question as to why the deleter type must be specified as part of the handle
type.

Warm regards,
Adi


On Mon, Sep 1, 2014 at 3:19 AM, David Krauss <potswa@gmail.com> wrote:

>
> On 2014=E2=80=9309=E2=80=9301, at 2:21 AM, Adi Shavit <adishavit@gmail.co=
m> wrote:
>
> For example, OpenGL has many components that are all referenced via simpl=
e
> int IDs.
> It is up-to the programmer to keep track of which int ID is which and how
> each (resource ) should be released.
>
>
> An excellent job for a class. Define one class per type of resource.
>
> The solution is to add your own indirect call into the deleter, such as b=
y
>> using a naked function pointer type as the deleter, or by virtual
>> operator ().
>>
>
> How would I do that if my deleter is actually a lambda?
>
>
> Captureless lambdas implicitly convert to a naked function pointer, and
> deleters are stateless/captureless, so use that alternative.
>
> It is often the case that a resource release function expects a ref to th=
e
> handle, so I would need to wrap it in some lamba.
>
>
> You don=E2=80=99t need a lambda; they have no special abilities that cann=
ot be
> attained otherwise. They can capture local variables, but your use case,
> along with most use cases of scoped_resource, precludes captures being
> very useful.
>
> If I have to write a class with a custom dtor for each of my resource
> kinds (not necessarily different types), then this whole discussion is mo=
ot
> as it means this class is not generic enough to let me apply RAII to any
> (simple) resource.
>
>
> Use a polymorphic class.
>
> For what it=E2=80=99s worth, I=E2=80=99m not convinced that scoped_resour=
ce provides any
>> useful encapsulation. Simply writing a class with a destructor is more
>> terse and more expository.
>>
>
>  When using a 3rd-party C-API (e.g. OpenGL) I often don't want to write a
> (yet-another) full blown wrapper library. I just want better resource
> management.
> It is always recommended that you handle your resource release at the
> point of creation (that is the essence of RAII) - and a resource wrapper
> should allow me to do this.
>
>
> You can define a polymorphic class locally.
>
> // header
> struct opengl_resource {
>     GLuint id;
>
>     opengl_resource( GLuint in_id ) : id( in_id ) {}
>     virtual ~ opengl_resource() =3D 0;
> };
> inline opengl_resource::~ opengl_resource() =3D default;
>
> typedef std::unique_ptr< opengl_resource > opengl_handle;
>
> // implementation
> void foo() {
>     struct shader : opengl_resource {
>         using opengl_resource::opengl_resource;
>         virtual ~ shader() {
>             glDeleteShader( id );
>         }
>     };
>     // Pass this handle out to any structure/function:
>     opengl_handle sh =3D std::make_unique< shader >( glCreateShader(
> GL_VERTEX_SHADER ) );
> }
>
> Over time, you can migrate the local classes into a wrapper library. Ther=
e
> is no commitment to either keeping everything local precluding reusabilit=
y
> nor to a =E2=80=9Cfull-blown=E2=80=9D library (although I don=E2=80=99t s=
ee the risk in developing
> such a thin library as you go).
>
> There is a little boilerplate, but it=E2=80=99s totally obvious how every=
thing
> works. No room for error.
>
> Destructors are (usually) implicitly noexcept, so using a non-noexcept
> function to define destructor functionality loses a little safety. The
> traditional way on the other hand is essentially perfect.
>
> Virtual destructors are among the most widely-known idioms in existence,
>> and simply =E2=80=9Cdoing things the old-fashioned way=E2=80=9D would li=
kely have avoided
>> this deleter confusion entirely.
>>
>
> I am not sure I understand how this applies to our discussion.
>
>
> Every workable solution deserves consideration. The apparent problem is
> merely that you believe classes should be declared in interface headers,
> but you want to have implementation classes. C++ has always supported
> implementation classes. Besides local classes, there are also unnamed
> namespaces. There is no need to go back to the bad old days of function
> pointers.
>
>  --
>
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/GP8BVeW_LkI/=
unsubscribe
> .
> To unsubscribe from this group and all its topics, send an email to
> std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>

--=20

---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

--001a11c2ba8e5111670501fb7d9e
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Hi David,<div><br></div><div>=C2=A0 Thank you for the deta=
iled explanation and the sample code.</div><div>Assuming we want/need to wr=
ite new small classes, your approach, indeed, reduces the amount of boilerp=
late and error-prone code and makes good use of unique_ptr.</div>

<div><br></div><div>Ultimately, I think that it is a question of style, tas=
te and context, whether to write small (efficient) wrappers or try to use a=
 generic wrapper (which amounts to about one extra line of user code if at =
all). As you mention, your suggestion is really an alternative to the class=
es proposed in this proposal and is always a valid option regardless if thi=
s proposal makes it into the standard or not.</div>

<div><br></div><div>I think that if your generalize and genericise the code=
 in your example, you will essentially get a version of scoped_resource san=
s virtual calls, and possibly sans deleter type in type - which is basicall=
y what I wanted.=C2=A0</div>

<div><br></div><div>Since this discussion is in the context of the proposal=
 itself (and more generally, its applicability to common use cases), I thin=
k your suggestion is important for understanding alternatives to common use=
 cases and any pros and cons each option has. It does not directly answer m=
y original question as to why the deleter type must be specified as part of=
 the handle type.</div>

<div><br></div><div>Warm regards,</div><div>Adi=C2=A0</div><div class=3D"gm=
ail_extra"><br><br><div class=3D"gmail_quote">On Mon, Sep 1, 2014 at 3:19 A=
M, David Krauss <span dir=3D"ltr">&lt;<a href=3D"mailto:potswa@gmail.com" t=
arget=3D"_blank">potswa@gmail.com</a>&gt;</span> wrote:<br>

<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex"><div style=3D"word-wrap:break-word"><br><div><div class=3D=
"">
<div>
On 2014=E2=80=9309=E2=80=9301, at 2:21 AM, Adi Shavit &lt;<a href=3D"mailto=
:adishavit@gmail.com" target=3D"_blank">adishavit@gmail.com</a>&gt; wrote:<=
/div><br><blockquote type=3D"cite"><div dir=3D"ltr"><div>For example, OpenG=
L has many components that are all referenced via simple int IDs.</div>

<div>It is up-to the programmer to keep track of which int ID is which and =
how each (resource ) should be released.=C2=A0</div></div></blockquote><div=
><br></div></div><div>An excellent job for a class. Define one class per ty=
pe of resource.</div>

<br><blockquote type=3D"cite"><div dir=3D"ltr"><blockquote class=3D"gmail_q=
uote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-c=
olor:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style=
=3D"word-wrap:break-word">

The solution is to add your own indirect call into the deleter, such as by =
using a naked function pointer type as the deleter, or by <font face=3D"Cou=
rier">virtual operator ()</font>.<br></div></blockquote><div class=3D""><di=
v>

<br></div><div>How would I do that if my deleter is actually a lambda?</div=
></div></div></blockquote><div><br></div><div>Captureless lambdas implicitl=
y convert to a naked function pointer, and deleters are stateless/capturele=
ss, so use that alternative.</div>

<div class=3D""><br><blockquote type=3D"cite"><div dir=3D"ltr"><div>It is o=
ften the case that a resource release function expects a ref to the handle,=
 so I would need to wrap it in some lamba.</div></div></blockquote><div><br=
>
</div>
</div><div>You don=E2=80=99t need a lambda; they have no special abilities =
that cannot be attained otherwise. They can capture local variables, but yo=
ur use case, along with most use cases of <font face=3D"Courier">scoped_res=
ource</font>, precludes captures being very useful.</div>

<div class=3D""><br><blockquote type=3D"cite"><div dir=3D"ltr"><div>If I ha=
ve to write a class with a custom dtor for each of my resource kinds (not n=
ecessarily different types), then this whole discussion is moot as it means=
 this class is not generic enough to let me apply RAII to any (simple) reso=
urce.</div>

</div></blockquote><div><br></div></div><div>Use a polymorphic class.</div>=
<div class=3D""><br><blockquote type=3D"cite"><div dir=3D"ltr"><blockquote =
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1=
px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:=
1ex">

<div style=3D"word-wrap:break-word">For what it=E2=80=99s worth, I=E2=80=99=
m not convinced that <font face=3D"Courier">scoped_resource</font> provides=
 any useful encapsulation. Simply writing a class with a destructor is more=
 terse and more expository.<br>

</div></blockquote><div><br></div><div>=C2=A0When using a 3rd-party C-API (=
e.g. OpenGL) I often don&#39;t want to write a (yet-another) full blown wra=
pper library. I just want better resource management.</div><div>It is alway=
s recommended that you handle your resource release at the point of creatio=
n (that is the essence of RAII) - and a resource wrapper should allow me to=
 do this.</div>

</div></blockquote><div><br></div></div><div>You can define a polymorphic c=
lass locally.</div><div><br></div><div><font face=3D"Courier">// header</fo=
nt></div><div><font face=3D"Courier">struct opengl_resource {</font></div>
<div>
<font face=3D"Courier">=C2=A0 =C2=A0 GLuint id;</font></div><div><font face=
=3D"Courier"><br></font></div><div><font face=3D"Courier">=C2=A0 =C2=A0 ope=
ngl_resource( GLuint in_id ) : id( in_id ) {}</font></div><div><font face=
=3D"Courier">=C2=A0 =C2=A0 virtual ~ opengl_resource() =3D 0;</font></div>

<div><font face=3D"Courier">};</font></div><div><font face=3D"Courier">inli=
ne opengl_resource::~ opengl_resource() =3D default;</font></div><div><font=
 face=3D"Courier"><br></font></div><div><font face=3D"Courier">typedef=C2=
=A0</font><span style=3D"font-family:Courier">std::unique_ptr&lt; opengl_re=
source &gt; opengl_handle;</span></div>

<div><font face=3D"Courier"><br></font></div><div><font face=3D"Courier">//=
 implementation</font></div><div><font face=3D"Courier">void foo() {</font>=
</div><div><font face=3D"Courier">=C2=A0 =C2=A0 struct shader : opengl_reso=
urce {</font></div>

<div><font face=3D"Courier">=C2=A0 =C2=A0 =C2=A0 =C2=A0 using opengl_resour=
ce::opengl_resource;</font></div><div><font face=3D"Courier">=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 virtual ~=C2=A0</font><span style=3D"font-family:Courier">sha=
der</span><font face=3D"Courier">() {</font></div>

<div><font face=3D"Courier">=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0=
glDeleteShader( id );</font></div><div><font face=3D"Courier">=C2=A0 =C2=A0=
 =C2=A0 =C2=A0 }</font></div><div><font face=3D"Courier">=C2=A0 =C2=A0 };</=
font></div><div><font face=3D"Courier">=C2=A0 =C2=A0 // Pass this=C2=A0hand=
le out to any structure/function:</font></div>

<div><font face=3D"Courier">=C2=A0 =C2=A0=C2=A0</font><span style=3D"font-f=
amily:Courier">opengl_handle</span><font face=3D"Courier">=C2=A0sh =3D std:=
:make_unique&lt; shader &gt;(=C2=A0glCreateShader( GL_VERTEX_SHADER )=C2=A0=
);</font></div><div><font face=3D"Courier">}</font></div>

<div><br></div><div>Over time, you can migrate the local classes into a wra=
pper library. There is no commitment to either keeping everything local pre=
cluding reusability nor to a =E2=80=9Cfull-blown=E2=80=9D library (although=
 I don=E2=80=99t see the risk in developing such a thin library as you go).=
</div>

<div><br></div><div>There is a little boilerplate, but it=E2=80=99s totally=
 obvious how everything works. No room for error.</div><div><br></div><div>=
Destructors are (usually) implicitly noexcept, so using a non-noexcept func=
tion to define destructor functionality loses a little safety. The traditio=
nal way on the other hand is essentially perfect.</div>

<div class=3D""><br><blockquote type=3D"cite"><div dir=3D"ltr"><blockquote =
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1=
px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:=
1ex">
<div style=3D"word-wrap:break-word">
Virtual destructors are among the most widely-known idioms in existence, an=
d simply =E2=80=9Cdoing things the old-fashioned way=E2=80=9D would likely =
have avoided this deleter confusion entirely.</div></blockquote><div><br></=
div><div>I am not sure I understand how this applies to our discussion.</di=
v>

</div></blockquote><br></div></div><div>Every workable solution deserves co=
nsideration. The apparent problem is merely that you believe classes should=
 be declared in interface headers, but you want to have implementation clas=
ses. C++ has always supported implementation classes. Besides local classes=
, there are also unnamed namespaces. There is no need to go back to the bad=
 old days of function pointers.</div>

<div><br></div></div><div class=3D""><div class=3D"h5">

<p></p>

-- <br>
<br>
--- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups &quot;ISO C++ Standard - Future Proposals&quot; group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/GP8BVeW_LkI/unsubscribe" target=3D"_blan=
k">https://groups.google.com/a/isocpp.org/d/topic/std-proposals/GP8BVeW_LkI=
/unsubscribe</a>.<br>


To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_blank">std-prop=
osals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>

<p></p>

-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--001a11c2ba8e5111670501fb7d9e--

.
