-
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
Implement Smart Pointer Creation With Default Initialization #1315
Implement Smart Pointer Creation With Default Initialization #1315
Conversation
I pushed a commit (deleting an extra newline) with the |
Status update: Planning to review this on Thursday, Oct 8. Apologies for the delay! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! This looks good, my main concern is with a potential corner case in overload resolution that should be avoidable with different metaprogramming. Please let me know if you'd like me to explain further, or I can revise the PR if you want - your preference.
Co-authored-by: Stephan T. Lavavej <[email protected]>
This looks great - thanks for the thorough and highly detailed work. (I noticed and appreciated the improvements like using I pushed a merge with
I'll find a second maintainer to review and then we can merge this! 🚀 |
_Uninitialized_rev_destroying_backout _Backout{_Out}; | ||
for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { | ||
_Backout._Emplace_back_for_overwrite(); | ||
} | ||
_Backout._Release(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we simplify this to
_Uninitialized_rev_destroying_backout _Backout{_Out}; | |
for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { | |
_Backout._Emplace_back_for_overwrite(); | |
} | |
_Backout._Release(); | |
_Uninitialized_default_construct_n(_Out, _Size); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no such function as _Uninitialized_default_construct_n
and we can't use uninitialized_default_construct_n
because it doesn't destroy elements in the reverse order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm there is the ranges version (where I found a unneeded specialization that I forgot to remove so thanks ;))
Should we also destroy in backwards order there?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ranges::uninitialized_default_construct_n
needs to support forward iterators and destroying in reverse order with them would be hard.
@@ -2351,6 +2369,25 @@ void _Uninitialized_value_construct_multidimensional_n(_Ty* const _Out, const si | |||
} | |||
} | |||
|
|||
template <class _Ty> | |||
void _Uninitialized_default_construct_multidimensional_n(_Ty* const _Out, const size_t _Size) { | |||
if constexpr (!is_trivially_default_constructible_v<_Ty>) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be absolutely sure, even for the meow_overwrite
we do not want to default initialize here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's the whole point of *_for_overwrite
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For better or worse, there are many places in the STL where we assume that we can omit default-initialization of objects that are trivially default constructible. I'm not sure the resulting behavior is portably defined, but it has been working as intended on our implementation. We may need to make changes if and when compilers complain about this trick in constexpr
, but that hasn't happened yet and in any case would need for more widespread changes than just this PR.
@@ -2351,6 +2369,25 @@ void _Uninitialized_value_construct_multidimensional_n(_Ty* const _Out, const si | |||
} | |||
} | |||
|
|||
template <class _Ty> | |||
void _Uninitialized_default_construct_multidimensional_n(_Ty* const _Out, const size_t _Size) { | |||
if constexpr (!is_trivially_default_constructible_v<_Ty>) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For better or worse, there are many places in the STL where we assume that we can omit default-initialization of objects that are trivially default constructible. I'm not sure the resulting behavior is portably defined, but it has been working as intended on our implementation. We may need to make changes if and when compilers complain about this trick in constexpr
, but that hasn't happened yet and in any case would need for more widespread changes than just this PR.
Thanks - the latest changes look good. I was concerned about debug codegen impact from increased use of Lines 281 to 290 in e7d5113
|
Thanks again for implementing this feature, @AdamBucior and @Weheineman! This will help users achieve maximum performance with Standard smart pointers. 🚀 |
Resolves #48. Based on #778.