<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Oct 3, 2014 at 12:55 PM, Jared Grubb <span dir="ltr"><<a href="mailto:jared.grubb@gmail.com" target="_blank">jared.grubb@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div>I spoke with Marshall briefly about this at CppCon. My suggestion is that std::function should either:</div><div> * correctly capture blocks and just work (as this patch does)</div><div> * compile with error if you try it (and also maybe add a convenience adaptor like you suggest to allow it to manually work)</div><div><br></div><div>The current problem is that if you write something like this:</div><div>   template <typename F> doSomething(F&& functor) { std::function<...> capturing = std::forward<F>(functor); ... }</div><div>This works great for lambdas. For blocks, it compiles just fine but has runtime issues.</div></div></blockquote><div><br></div><div>What runtime issues are you referring to? Could you provide a simple standalone complete example?<br><br>I assume the issue is that std::function will capture the block's (presumably raw) pointer by value but do none of the increment/decrement. This doesn't seem necessarily broken & I'm not sure (for myself) it merits library support to protect.<br><br>This would be the same behavior as any other lifetime issues with pointer captures.<br><br>  std::function<...> func() {<br>    int i;<br>    int *j = &i;<br>    return [=j] () { ... }; // captured j by value, but it points to something that goes out of scope at the end of the function. Bad.<br>  }<br><br>But similar code isn't a problem at all:<br><br></div><div>  void func(std::function<...>); // func calls the std::function, maybe copies it around, but doesn't copy it to global storage/anywhere that outlives the <br>  ...<br>  int i;<br>  int *j = &i;<br>  func([=j]() { ... });<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><br></div><div>Marshall suggested to me that we just make it work, so that's the approach I've taken here. I agree it is a bit "un-pure" to add something like this into libcxx, but given that clang handles blocks natively (with -fblocks), maybe that's ok.</div><div><br></div><div>But, after looking over this patch if it doesnt feel right, I would at least suggest we add =delete/enable_if's to the right places so at least incorrect code wont compile.</div><span class="HOEnZb"><font color="#888888"><div><br></div><div>Jared</div></font></span><div><div class="h5"><br><div><blockquote type="cite"><div>On Oct 1, 2014, at 14:57, David Blaikie <<a href="mailto:dblaikie@gmail.com" target="_blank">dblaikie@gmail.com</a>> wrote:</div><br><div><div dir="ltr">[+Marshall as libc++ maintainer]<br><br>What would it look like if we just provided a value-semantic-C++ wrapper around blocks, translating C++ move/copy operations down to the Block_copy/release/etc operations?<br><br>That way it'd be orthogonal to the type erasure of std::function and could be used just for a convenience when using blocks in C++ code anyway:<br><br>  auto x = make_cpp_block(/* block stuff */);<br>  auto y = x;<br>  x();<br>  etc... <br><br>(& then you'd compose them with "std::function<...> f = make_cpp_block(...);" (the block wrapper could have an implicit conversion to std::function)) <br><br>It's a little more text, but doesn't require an extension to the standard library, and can be used independently.<br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Oct 1, 2014 at 11:38 AM, Jared Grubb <span dir="ltr"><<a href="mailto:jared.grubb@gmail.com" target="_blank">jared.grubb@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">== Background:<br>
std::function will wrap anything that is callable (and can be copied/moved). Blocks are copyable and callable, however you need to use the reference counting Block_copy/Block_release functions.<br>
<br>
== Request for Comment on the Patch:<br>
I am working on a patch that will allow std::function to capture blocks correctly (under the right feature guards).<br>
<br>
Functionally, the patch is complete. However, it's not checkin-ready as I had a couple questions on the approach:<br>
 * Is the approach right? I specialized the __func storage class, as that seems to be the right thing to customize.<br>
 * I have included some unit test implementations. There are quite a few std::function unit tests, so I wanted to make sure I was on the right track before I do all of them.<br>
 * Should I add tests for ObjC++ code, under ARC and non-ARC scenarios? There are no ObjC++ files in libcxx, and the test-runner does not yet support them. Adding this is not hard, but it's a change in how things are today.<br>
<br>
If this looks like it's on the right track, I will flush out the rest of the unit tests, and optionally add ObjC++ unit tests.<br>
<br>
<br><br>
<br>
Jared<br>
<br>
<br>_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@cs.uiuc.edu" target="_blank">cfe-dev@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev</a><br>
<br></blockquote></div><br></div></div>
</div></blockquote></div><br></div></div></div></blockquote></div><br></div></div>