-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
<functional>: Avoid pessimization in std::move_only_function
assignment operators
#2278
Comments
The lack of Exception safety isn't the only concern either; reentrancy is also something solved by the move-and-swap formulation (i.e., destroying the current target of |
I'm also not seeing how this is observable. Nothing in the specification of |
Allocator support was already removed from
So can I just implement these operations as I proposed, without changed wording? |
Re allocator: Please DON'T (I know, you are probably not the one to decide on this). What would be much more useful is a guaranteed minimal size for the small buffer. If I know that objects smaller than e.g. two pointers doesn't get allocated on the heap, I can create my own wrapper for the callable that takes care of allocation. Speaking of which (sorry for the slight off topic): Could you please talk to the libc++ and libstdc++ guys and see if you can agree on a common size for SBO? Re observability: Maybe I'm missunderstanding your concern, but if the standard guarantees that after
f1 contains callable2., then that's of course an observable property. Most obviously, I'm allowed to do |
My concern for observability was the number of move constructor of callable in SBO case. |
You have this. [func.wrap.func.con]/14:
[func.wrap.mov.con]/22
I think no-bad_alloc is unimplementable if SBO cannot fit a pointer |
I don't think there's something to agree on, as libc++ has no
libstdc++ |
I admit I had hoped for something a little more.
Sorry, I specifically meant SBO size for
at least on x64 its two pointers afaik. |
Since the optimizations to special case to destroy small-trivially-destructible and move small-trivially-moveable or large functors are there, I'm taking advantages of this information to optimize swap:
See here This avoids any potentially observable difference against the standard, whereas still optimizing many cases, and the checks are fused with the optimization checks that would otherwise have been there anyway. I'm satisfied with this enough to avoid raising this issue. |
If I understand you correctly, I think this is not correct: If move assign is specified in terms of swap, then the moved from object must contain the old callable after the operation is completed.
It has also an effect on the order inwhich the the destructors ofr callable1 and callable2 should be run |
Not exactly. Move assignment is specified in terms of
So first the |
That makes sense. Thanks for explaining |
Thanks for looking into this. After thinking about this issue and your implementation, I think it would be reasonable to file an LWG issue, but I believe there's a moderate chance of it being resolved as Not A Defect. I also think that your current implementation in #2267 is an efficient way to handle the current wording. |
This is LWG-3642 now |
Should we close this?
|
Yes, I'm happy to close this and wait for LWG-3642 to tell us what (if anything) to change. |
Towards #182. - This PR drops all section numbers except for D.x in `<yvals_core.h>`. I decided to cite WG21-N4868 for C++20 deprecation. - Some citations in `<format>` are intentionally not updated because WG21-P2675R1 and LWG-3631 are not implemented yet. - Citations in test files are not updated, but I think I'll do it soon. - Drive-by change: a comment for `move_only_function`'s move assignment operator explaining why it's `noexcept(false)` (see #3565 (comment) and #2278 (comment)). --------- Co-authored-by: Stephan T. Lavavej <[email protected]> Co-authored-by: Nicole Mazzuca <[email protected]> Co-authored-by: Casey Carter <[email protected]>
Does the below look like a valid LWG issue?
In
std::move_only_function
wg21-p0288, some assignments are defined in terms ofswap
(in [func.wrap.mov.con])The implementation of assignment via swap is normally useful for exception safety.
However, this is superfluous here, as
move_only_function
is moved withnoexcept
.At the same time, this approach causes extra moving of function. This may be expensive due to large small-functor-optimization buffer, and due to calling user-provided move constructor for small factor.
Looks like the optimizations made by implementation to avoid extra moving cannot always be made, as calling user-provided move constructor is observable.
I propose:
addnocexcept
to move assingmentmove_only_function& operator=(move_only_function&& f) noexcept;
change the mentioned methods to say:
The text was updated successfully, but these errors were encountered: