<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><div>On Feb 10, 2011, at 6:56 AM, Bruno Santos wrote:</div><br><blockquote type="cite"><div><blockquote type="cite"><br></blockquote><blockquote type="cite">Why is the following structure incapable of describing a C++ lambda<br></blockquote><blockquote type="cite">function? <br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">struct Block_basic {<br></blockquote><blockquote type="cite">    void *isa;<br></blockquote><blockquote type="cite">    int Block_flags;  /* int32_t */<br></blockquote><blockquote type="cite">    int Block_size; /* XXX should be packed into Block_flags */<br></blockquote><blockquote type="cite">    void (*Block_invoke)(void *);<br></blockquote><blockquote type="cite">    void (*Block_copy)(void *dst, void *src);  /* iff<br></blockquote><blockquote type="cite">BLOCK_HAS_COPY_DISPOSE */<br></blockquote><blockquote type="cite">    void (*Block_dispose)(void *);             /* iff<br></blockquote><blockquote type="cite">BLOCK_HAS_COPY_DISPOSE */<br></blockquote><blockquote type="cite">    /* long params[0];  // where const imports, __block storage<br></blockquote><blockquote type="cite">references, etc. get laid down */<br></blockquote><blockquote type="cite">};<br></blockquote><blockquote type="cite"><br></blockquote><br>It can't, a lambda can be used as a function pointer!<br><br>Lambdas are syntactic sugar for function objects, which is fundamentally<br>different from what blocks are. What you are asking is lot of baggage<br>for nothing, from a pure C++ perspective, just to be compatible with<br>blocks.<br></div></blockquote><br></div><div><br></div><div><br></div><div>A function object is a class with a set of data members and a callback function called 'operator()()'.</div><div>A 'block' is a callback function and a set of captured data items. </div><div><br></div><div>How is that different? </div><div><br></div><div><br></div><div>consider....</div><div><br></div><div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; color: rgb(120, 73, 43); ">#ifdef __BLOCKS__</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; color: rgb(185, 45, 161); ">void</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; ">dispatch_sync(<span style="color: #4f8187">dispatch_queue_t</span> dq, <span style="color: #b92da1">void</span> (^work)(<span style="color: #b92da1">void</span>))</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; ">{</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; "><span class="Apple-tab-span" style="white-space:pre">        </span><span style="color: #b92da1">struct</span> Block_basic *bb = (<span style="color: #b92da1">void</span> *)work;</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; "><span class="Apple-tab-span" style="white-space:pre">        </span><span style="color: #32595d">dispatch_sync_f</span>(dq, work, (<span style="color: #4f8187">dispatch_function_t</span>)bb-><span style="color: #703da9">Block_invoke</span>);</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; ">}</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; color: rgb(120, 73, 43); ">#endif</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; min-height: 13px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; ">DISPATCH_NOINLINE</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; color: rgb(185, 45, 161); ">void</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; ">dispatch_sync_f(<span style="color: #4f8187">dispatch_queue_t</span> dq, <span style="color: #b92da1">void</span> *ctxt, <span style="color: #4f8187">dispatch_function_t</span> func)</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; ">{</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; "><span class="Apple-tab-span" style="white-space:pre">  </span>...</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; "><span class="Apple-tab-span" style="white-space:pre">   </span>func(ctxt);</div></div><div><br></div><div><br></div><div><br></div><div>What do I see in this code and Block_basic?  I see a callback function (func = Block_invoke), a 'this' pointer (ctxt is a Block_basic instance), a destructor (Block_dispose), and a cloning operation (Block_copy). I even see a 'isa' pointer (analogous to vtable pointer).   What is does a single-inheritance C++ class have that this mechanism doesn't have? </div><div><br></div><div><br></div><div>If all you do is set the system up so that if a lambda-to-block conversion is requested, the Block_basic structure is set up and mapped to the lambda, that would be enough.  If you did that, then lambdas could be passed to libdispatch and the various cocoa/foundation functions that accept blocks as arguments. The developer writes his lambda and passes it to the apple function that accepts blocks....oblivious to the fact that a conversion has taken place.  In the case where the lambda is entirely known at compile time and it is known that is is only converted to a block, then you can optimize the situation by just making it into a block at compile time.</div><div><br></div><div><br></div><div><div>I really don't understand what the objection to the concept is. The technical objections I've seen don't seem substantial to me when I look at the details. Do you think easy interoperability between standard technologies and platform-specific technologies is not a desirable goal?  </div></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div></body></html>