<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>C++, Qt et GPU &#187; germinolegrand</title>
	<atom:link href="https://blog.developpez.com/gpu/?author=395292&#038;feed=rss2" rel="self" type="application/rss+xml" />
	<link>https://blog.developpez.com/gpu</link>
	<description></description>
	<lastBuildDate>Fri, 24 May 2013 17:02:21 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.42</generator>
	<item>
		<title>Lambdas T() et std::function&lt;const T&amp;&gt;, un mélange dangereux</title>
		<link>https://blog.developpez.com/gpu/?p=309</link>
		<comments>https://blog.developpez.com/gpu/?p=309#comments</comments>
		<pubDate>Wed, 15 May 2013 00:49:31 +0000</pubDate>
		<dc:creator><![CDATA[germinolegrand]]></dc:creator>
				<category><![CDATA[Avancé]]></category>
		<category><![CDATA[C++]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/gpu/?p=309</guid>
		<description><![CDATA[Le chat de Dvp est le lieu de rendez-vous quotidien des devs C++ et de nombreuses discussions techniques sur le C++ soulèvent des interrogations sur des points particuliers du langage. Il nous est apparu qu&#8217;une faille dangereuse et non détectée &#8230; <a href="https://blog.developpez.com/gpu/?p=309">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Le chat de Dvp est le lieu de rendez-vous quotidien des devs C++ et de nombreuses discussions techniques sur le C++ soulèvent des interrogations sur des points particuliers du langage.</p>
<p>Il nous est apparu qu&rsquo;une faille dangereuse et non détectée par le compilateur résultait de l&rsquo;utilisation conjointe de la déduction automatique de type retour des lambdas et des std::function&lt;const A&amp;()&gt; qui retournent une référence constante.</p>
<p><span id="more-309"></span></p>
<p>Le code suivant compile parfaitement sans aucun warning sous g++4.8 et clang++3.2 avec les flags <code class="codecolorer text blackboard"><span class="text">-pedantic -Wall -Wextra</span></code>.</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339900;">#include &lt;iostream&gt;</span><br />
<span style="color: #339900;">#include &lt;functional&gt;</span><br />
<br />
<span style="color: #0000ff;">struct</span> A<br />
<span style="color: #008000;">&#123;</span> <br />
&nbsp; &nbsp; A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;A()&quot;</span> <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; ~A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;~A()&quot;</span> <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">32</span><span style="color: #008080;">;</span><span style="color: #666666;">//variable témoin</span><br />
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span><br />
&nbsp;<br />
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; A a<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; std<span style="color: #008080;">::</span><span style="color: #007788;">function</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">const</span> A<span style="color: #000040;">&amp;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #000080;">&gt;</span> f <span style="color: #000080;">=</span> <span style="color: #008000;">&#91;</span><span style="color: #000040;">&amp;</span>a<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#123;</span><span style="color: #0000ff;">return</span> a<span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">const</span> A<span style="color: #000040;">&amp;</span> aref <span style="color: #000080;">=</span> f<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;checkpoint_1&quot;</span> <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> aref.<span style="color: #007788;">i</span> <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<p>Or le résultat obtenu en commentant cette ligne est :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;`<br />
~A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><br />
checkpoint_1<br />
<span style="color: #0000dd;">1</span><br />
~A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span></div></td></tr></tbody></table></div>
<p>Pour les rapides, oui aref est totalement corrompue, et son utilisation résulte en un crash sauvage et sans pitié du programme lorsqu&rsquo;on a de la chance. Pour les autres, voici l&rsquo;explication.</p>
<p>Savez-vous quel est le type de retour implicite de la lambda ci-dessous ?</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">A a<span style="color: #008080;">;</span><br />
<span style="color: #0000ff;">auto</span> lm <span style="color: #000080;">=</span> <span style="color: #008000;">&#91;</span><span style="color: #000040;">&amp;</span>a<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#123;</span><span style="color: #0000ff;">return</span> a<span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>
<p>Si comme moi, à première vue vous répondez A&amp;, vous vous en mordrez les doigts.<br />
La réponse est A.</p>
<p>En effet, comment se déduit automatiquement le type de retour d&#039;une lambda ? Eh bien de la même façon que decltype. C&#039;est à dire tel que la variable a été déclarée. Ici, a étant déclaré comme A, c&#039;est donc A qui est le type du retour de la lambda.</p>
<p>Si l&#039;on capture cette fois une référence vers A :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">A a<span style="color: #008080;">;</span><br />
A<span style="color: #000040;">&amp;</span> refTo_a<span style="color: #008000;">&#40;</span>a<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #0000ff;">auto</span> lm <span style="color: #000080;">=</span> <span style="color: #008000;">&#91;</span><span style="color: #000040;">&amp;</span>refTo_a<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#123;</span><span style="color: #0000ff;">return</span> refTo_a<span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>
<p>Ici refTo_a est déclarée comme une A&amp;, c&#039;est donc A&amp; qui sera déduit.</p>
<p>Reprenons notre cas initial. Bon, à priori ce n&#039;est pas une grande perte, on fait une simple copie.</p>
<p>Ainsi, le code suivant est parfaitement sain si on reconnait la légitimité de la copie :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339900;">#include &lt;iostream&gt;</span><br />
<span style="color: #339900;">#include &lt;functional&gt;</span><br />
<br />
<span style="color: #0000ff;">static</span> <span style="color: #0000ff;">int</span> ID <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span><br />
<br />
<span style="color: #0000ff;">struct</span> A<br />
<span style="color: #008000;">&#123;</span> <br />
&nbsp; &nbsp; A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> id <span style="color: #000080;">=</span> ID<span style="color: #000040;">++</span><span style="color: #008080;">;</span> std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;A() &quot;</span> <span style="color: #000080;">&lt;&lt;</span> id <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; A<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> A<span style="color: #000040;">&amp;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> id <span style="color: #000080;">=</span> ID<span style="color: #000040;">++</span><span style="color: #008080;">;</span> std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;A(const A&amp;) &quot;</span> <span style="color: #000080;">&lt;&lt;</span> id <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; ~A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;~A() &quot;</span> <span style="color: #000080;">&lt;&lt;</span> id <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">32</span><span style="color: #008080;">;</span><span style="color: #666666;">//variable témoin</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">int</span> id <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span><br />
&nbsp;<br />
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; A a<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">auto</span> lm <span style="color: #000080;">=</span> <span style="color: #008000;">&#91;</span><span style="color: #000040;">&amp;</span>a<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#123;</span><span style="color: #0000ff;">return</span> a<span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">const</span> A<span style="color: #000040;">&amp;</span> aref <span style="color: #000080;">=</span> lm<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;checkpoint_1&quot;</span> <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> aref.<span style="color: #007788;">i</span> <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000dd;">0</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;`<br />
A<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> A<span style="color: #000040;">&amp;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000dd;">1</span><br />
checkpoint_1<br />
<span style="color: #0000dd;">32</span><br />
~A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000dd;">1</span><br />
~A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000dd;">0</span></div></td></tr></tbody></table></div>
<p>La prise par référence constante allonge bien la durée de vie de la temporaire retournée par la lambda jusqu&#039;à la fin de la vie de la référence, ainsi que la norme le demande.</p>
<p>Oui mais&#8230;</p>
<p>Que se passe-t-il lorsque notre lambda est encapsulée dans une std::function&lt;const A&amp;()&gt; ?</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339900;">#include &lt;iostream&gt;</span><br />
<span style="color: #339900;">#include &lt;functional&gt;</span><br />
<br />
<span style="color: #0000ff;">static</span> <span style="color: #0000ff;">int</span> ID <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span><br />
<br />
<span style="color: #0000ff;">struct</span> A<br />
<span style="color: #008000;">&#123;</span> <br />
&nbsp; &nbsp; A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> id <span style="color: #000080;">=</span> ID<span style="color: #000040;">++</span><span style="color: #008080;">;</span> std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;A() &quot;</span> <span style="color: #000080;">&lt;&lt;</span> id <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; A<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> A<span style="color: #000040;">&amp;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> id <span style="color: #000080;">=</span> ID<span style="color: #000040;">++</span><span style="color: #008080;">;</span> std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;A(const A&amp;) &quot;</span> <span style="color: #000080;">&lt;&lt;</span> id <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; ~A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;~A() &quot;</span> <span style="color: #000080;">&lt;&lt;</span> id <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">32</span><span style="color: #008080;">;</span><span style="color: #666666;">//variable témoin</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">int</span> id <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span><br />
&nbsp;<br />
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; A a<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; std<span style="color: #008080;">::</span><span style="color: #007788;">function</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">const</span> A<span style="color: #000040;">&amp;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #000080;">&gt;</span> f <span style="color: #000080;">=</span> <span style="color: #008000;">&#91;</span><span style="color: #000040;">&amp;</span>a<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#123;</span><span style="color: #0000ff;">return</span> a<span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">const</span> A<span style="color: #000040;">&amp;</span> aref <span style="color: #000080;">=</span> f<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;checkpoint_1&quot;</span> <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<p>Ainsi que cela a été révélé plus haut, mais en ajoutant l&#039;indication du constructeur de copie et un id aux objets la sortie est :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000dd;">0</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;`<br />
A<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> A<span style="color: #000040;">&amp;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000dd;">1</span><br />
~A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000dd;">1</span><br />
checkpoint_1<br />
~A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000dd;">0</span></div></td></tr></tbody></table></div>
<p>Lors de l&#039;appel à f(), une copie est donc faite, conformément à ce qu&#039;on a vu précédemment avec la déduction automatique du type de la lambda. Mais elle est détruite immédiatement !</p>
<p>Pourtant on récupère bien une const A&amp;, pourquoi ne fait-elle pas prolonger de la copie temporaire comme précédemment ?</p>
<p>Un petit code montrant le mécanisme du avec std::function&lt;const A&amp;()&gt; en détail :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">static</span> <span style="color: #0000ff;">int</span> ID <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span><br />
<br />
<span style="color: #0000ff;">struct</span> A<br />
<span style="color: #008000;">&#123;</span> <br />
&nbsp; &nbsp; A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> id <span style="color: #000080;">=</span> ID<span style="color: #000040;">++</span><span style="color: #008080;">;</span> std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;A() &quot;</span> <span style="color: #000080;">&lt;&lt;</span> id <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; A<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> A<span style="color: #000040;">&amp;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> id <span style="color: #000080;">=</span> ID<span style="color: #000040;">++</span><span style="color: #008080;">;</span> std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;A(const A&amp;) &quot;</span> <span style="color: #000080;">&lt;&lt;</span> id <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; ~A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;~A() &quot;</span> <span style="color: #000080;">&lt;&lt;</span> id <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">32</span><span style="color: #008080;">;</span><span style="color: #666666;">//variable témoin</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">int</span> id <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span><br />
<br />
A lambda<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; A a<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">return</span> a<span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span><br />
<br />
<span style="color: #0000ff;">const</span> A<span style="color: #000040;">&amp;</span> function<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">const</span> A<span style="color: #000040;">&amp;</span> aret <span style="color: #000080;">=</span> lambda<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<br />
&nbsp; &nbsp; std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;checkpoint_1&quot;</span><span style="color: #008080;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0000ff;">return</span> aret<span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span><br />
<br />
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">const</span> A <span style="color: #000040;">&amp;</span>aref <span style="color: #000080;">=</span> function<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<br />
&nbsp; &nbsp; std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;checkpoint_2&quot;</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>
<p>On note à nouveau un silence total du compilateur. Le résultat est :</p>
<div class="codecolorer-container cpp blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000dd;">0</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;`<br />
checkpoint_1<br />
~A<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000dd;">0</span><br />
checkpoint_2</div></td></tr></tbody></table></div>
<p>Là où ça devient tordu c&#039;est que l&#039;extension de durée de vie d&#039;une temporaire par référence constante est limitée à une seule fois.</p>
<p>En effet, une fois récupérée dans une const A&amp;, la copie temporaire n&#039;a plus du tout le statut de temporaire : aussi on ne peut donc plus étendre sa durée de vie de cette façon !</p>
<p>Voici donc le pourquoi du comment. En conclusion il est donc dangereux soit de jouer avec les std::function&lt;const A&amp;()&gt; soit de laisser faire la déduction automatique du type retour des lambdas. En l&#039;absence d&#039;arguments forts pour pencher la balance, la vigilance est donc de mise lorsque l&#039;on joue avec les deux règles responsables du problème ici :</p>
<ol>
<li>Un type de retour automatiquement déduit est équivalent à un decltype(<em>expression_de_return</em>), soit le type de l&rsquo;expression telle qu&rsquo;elle a été déclarée, la capture par référence n&rsquo;y fait rien, ça reste le type de la variable avant sa capture.</li>
<li>Si une lambda a vocation à être stockée dans une std::function, alors il faut veiller à ce qu&rsquo;elle ne renvoie pas une temporaire et que le type de la std::function corresponde au comportement souhaité.</li>
</ol>
<p>Un grand merci à Flob90 qui a pris le temps de faire beaucoup de tests que vous pouvez consulter ici : <a href="http://pastebin.com/TR7f8rB2" title="lien pastebin" target="_blank">lien pastebin</a>. Merci à gbdivers pour sa relecture attentive.</p>
<p>Vous pouvez commenter ce billet de blog sur le <a href="http://www.developpez.net/forums/d1343028/cpp/billet-lambdas-t-stdfunctionltconst-tampgt-melange-dangereux/">forum</a>.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
