⭘ W. James MacLean ⭘ Software Engineer ⭘ Google Waterloo, Canada |
--
You received this message because you are subscribed to the Google Groups "cxx" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cxx+uns...@chromium.org.
To post to this group, send email to c...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CADAYvoc172Qpx_XygMzS3A9i7qUFWvrpbBHCm3L_NX7gP2V8MQ%40mail.gmail.com.
Can you explain why base::Bind is insufficient? We already have a way to make callable objects (Bind) and would prefer to not introduce a second.
It's not that base::Bind is insufficient, but the code ends up looking simpler with std::function. I thought since we now allow closures, this would complement them nicely.
--
You received this message because you are subscribed to the Google Groups "cxx" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cxx+uns...@chromium.org.
To post to this group, send email to c...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CAHtyhaQEebj_QDLX3kCzmL%2Bri%2B5zxXwLoCfV8GOM%2B7Q%2B-av_Kw%40mail.gmail.com.
1) 'Lambda Expressions' section allows _capturing_ lambdas for simple cases except "do not bind or store any capturing lambdas outside the lifetime of the stack frame they are defined in; use base::Callback for this instead"
2) chromium-cpp.appspot.com marks std::function as banned but we already use it implicitly (via auto) in many places:
https://cs.chromium.org/search/?q=%22%3D+%5B%26%22&sq=package:chromium&type=cs
auto f = []() { ... };// ...
f(); // Faster than a call via std::function.
I should read it as "any callable objects allowed to store a lambda except std::function".
I think, I have just three choices to implement a visitor pattern and use with capturing lambdas:
Given target.Visit(visitor)
1) Make |Visit| a template function to receive any callable object as an argument
2) Make |Visit| to receive base::Callback as an argument.
3) Write custom iterators and use range-based for loop (no lambdas needed).
PK
On Friday, May 11, 2018 at 5:46:10 PM UTC+10, Peter Kasting wrote:On Fri, May 11, 2018 at 12:13 AM loyso via cxx <c...@chromium.org> wrote:I think, I have just three choices to implement a visitor pattern and use with capturing lambdas:
Given target.Visit(visitor)
1) Make |Visit| a template function to receive any callable object as an argument
2) Make |Visit| to receive base::Callback as an argument.
3) Write custom iterators and use range-based for loop (no lambdas needed).Generally, do (2); rarely, do (3).Don't do (1).May I ask, why? :)
And why std::function (say, an option 4) is banned to use in this simple case?
--
You received this message because you are subscribed to the Google Groups "cxx" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cxx+uns...@chromium.org.
To post to this group, send email to c...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/cxx/e91b9220-b2f0-47ec-bc18-be850075f0dc%40chromium.org.
Well, using Callback everywhere leads to the following verbosity:
Forced Callback everywhere:int unmounted_count = 0;DoForEveryUnmountedCryptohome(base::Bind([](int* count, const base::FilePath&) { ++(*count); }, &unmounted_count));
instead of much simpler:int unmounted_count = 0;DoForEveryUnmountedCryptohome(base::Bind([&unmounted_count](const base::FilePath&) { ++unmounted_count; }));
On Friday, May 11, 2018 at 6:01:31 PM UTC+10, Peter Kasting wrote:On Fri, May 11, 2018 at 12:55 AM <lo...@chromium.org> wrote:On Friday, May 11, 2018 at 5:46:10 PM UTC+10, Peter Kasting wrote:On Fri, May 11, 2018 at 12:13 AM loyso via cxx <c...@chromium.org> wrote:I think, I have just three choices to implement a visitor pattern and use with capturing lambdas:
Given target.Visit(visitor)
1) Make |Visit| a template function to receive any callable object as an argument
2) Make |Visit| to receive base::Callback as an argument.
3) Write custom iterators and use range-based for loop (no lambdas needed).Generally, do (2); rarely, do (3).Don't do (1).May I ask, why? :)Because we already have Callback for that. The point of Callback is for people to use it consistently for "callable thing that is passed around". Even if all other solutions are equal in all other ways (which they're not, see notes on why we prefer Callback over std::function), we should standardize on one pattern, and Callback is that one.And why std::function (say, an option 4) is banned to use in this simple case?Again, because we have Callback and should use it in any case where someone would use a std::function.In a lot of these cases, it doesn't even come down to what the best possible option for some specific scenario is; it comes down to have simple rules like "always use Callback" that are at least good enough all the time.PK
--
You received this message because you are subscribed to the Google Groups "cxx" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cxx+uns...@chromium.org.
To post to this group, send email to c...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/cxx/2c14de8f-5bbb-4d07-a416-41c71fcc79dc%40chromium.org.
On Fri, May 11, 2018 at 5:19 PM <lo...@chromium.org> wrote:Well, using Callback everywhere leads to the following verbosity:
Forced Callback everywhere:int unmounted_count = 0;DoForEveryUnmountedCryptohome(base::Bind([](int* count, const base::FilePath&) { ++(*count); }, &unmounted_count));
instead of much simpler:int unmounted_count = 0;DoForEveryUnmountedCryptohome(base::Bind([&unmounted_count](const base::FilePath&) { ++unmounted_count; }));(I don't think this is very simpler than the above, but)I think this is OK as long as DoForEveryUnmountedCryptohome doesn't save the passed Callback to anywhere (just call it X times and return). That's clearly true according to the code -- the function name and the use of unmounted_count after the call should be sufficient to prove that.Or am I misreading the style guide?
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CAFJcur8mpd3drVSvL3K74dPX1nkhtVQDnaEYkTMV8_2iH9r2Ow%40mail.gmail.com.
On Fri, May 11, 2018 at 5:22 AM, Yuta Kitamura <yu...@chromium.org> wrote:On Fri, May 11, 2018 at 5:19 PM <lo...@chromium.org> wrote:Well, using Callback everywhere leads to the following verbosity:
Forced Callback everywhere:int unmounted_count = 0;DoForEveryUnmountedCryptohome(base::Bind([](int* count, const base::FilePath&) { ++(*count); }, &unmounted_count));
instead of much simpler:int unmounted_count = 0;DoForEveryUnmountedCryptohome(base::Bind([&unmounted_count](const base::FilePath&) { ++unmounted_count; }));(I don't think this is very simpler than the above, but)I think this is OK as long as DoForEveryUnmountedCryptohome doesn't save the passed Callback to anywhere (just call it X times and return). That's clearly true according to the code -- the function name and the use of unmounted_count after the call should be sufficient to prove that.Or am I misreading the style guide?Using a capturing lambda here is fine because it doesn't escape the local scope, and works if DoForEveryUnmountedCryptohome if a template (which is entirely reasonable in some places, and unreasonable in others). Outside of tests, we don't allow making a base::Callback from a capturing lambda, because we want to provide the guard rails that base::Bind has. We're willing to pay the occasional extra verbosity for catching errors in production code.
On Saturday, May 12, 2018 at 12:14:42 AM UTC+10, Jeremy Roman wrote:On Fri, May 11, 2018 at 5:22 AM, Yuta Kitamura <yu...@chromium.org> wrote:On Fri, May 11, 2018 at 5:19 PM <lo...@chromium.org> wrote:Well, using Callback everywhere leads to the following verbosity:
Forced Callback everywhere:int unmounted_count = 0;DoForEveryUnmountedCryptohome(base::Bind([](int* count, const base::FilePath&) { ++(*count); }, &unmounted_count));
instead of much simpler:int unmounted_count = 0;DoForEveryUnmountedCryptohome(base::Bind([&unmounted_count](const base::FilePath&) { ++unmounted_count; }));(I don't think this is very simpler than the above, but)I think this is OK as long as DoForEveryUnmountedCryptohome doesn't save the passed Callback to anywhere (just call it X times and return). That's clearly true according to the code -- the function name and the use of unmounted_count after the call should be sufficient to prove that.Or am I misreading the style guide?Using a capturing lambda here is fine because it doesn't escape the local scope, and works if DoForEveryUnmountedCryptohome if a template (which is entirely reasonable in some places, and unreasonable in others). Outside of tests, we don't allow making a base::Callback from a capturing lambda, because we want to provide the guard rails that base::Bind has. We're willing to pay the occasional extra verbosity for catching errors in production code.And by guard rails you also mean an ongoing migration to BindOnce and BindRepeatedly, right?
Will it affect the code in my example? Will we wrap |unmounted_count| into scoped_refptr to bypass raw pointer guards?
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/cxx/7b73b3fe-1d46-45a7-8fb8-c65dada66376%40chromium.org.