-
Notifications
You must be signed in to change notification settings - Fork 1.6k
<memory>(mostly): Uses-Allocator and guaranteed copy elision For piecewise construction #421
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
Changes from all commits
bc81f4a
0d4acf5
ed041ad
e9fd2f2
78b8110
312cf73
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,6 +15,10 @@ | |
| #include <xatomic.h> | ||
| #include <xutility> | ||
|
|
||
| #if _HAS_CXX20 | ||
| #include <tuple> | ||
| #endif // _HAS_CXX20 | ||
|
|
||
| #pragma pack(push, _CRT_PACKING) | ||
| #pragma warning(push, _STL_WARNING_LEVEL) | ||
| #pragma warning(disable : _STL_DISABLED_WARNINGS) | ||
|
|
@@ -2068,6 +2072,98 @@ void _Erase_nodes_if(_Container& _Cont, _Pr _Pred) { // erase each element satis | |
| } | ||
| } | ||
| } | ||
|
|
||
| #if _HAS_CXX20 | ||
|
|
||
| template <class _Ty, class _Alloc, class... _Types, enable_if_t<!_Is_specialization_v<_Ty, pair>, int> = 0> | ||
| constexpr auto uses_allocator_construction_args(const _Alloc& _Al, _Types&&... _Args) noexcept { | ||
| if constexpr (!uses_allocator_v<_Ty, _Alloc>) { | ||
| static_assert(is_constructible_v<_Ty, _Types...>, | ||
| "T must be constructible from Types... if uses_allocator_v<T, Alloc> is false"); | ||
| (void) _Al; | ||
| return _STD forward_as_tuple(_STD forward<_Types>(_Args)...); | ||
| } else { | ||
| if constexpr (is_constructible_v<_Ty, allocator_arg_t, const _Alloc&, _Types...>) { | ||
| using _Return_type = tuple<allocator_arg_t, const _Alloc&, _Types&&...>; | ||
| return _ReturnType(allocator_arg, _Al, _STD forward<_Types>(_Args)...); | ||
| } else if constexpr (is_constructible_v<_Ty, _Types..., const _Alloc&>) { | ||
| return _STD forward_as_tuple(_STD forward<_Types>(_Args)..., _Al); | ||
| } else { | ||
| static_assert(_Always_false<_Ty>, | ||
| "T must be constructible from either (allocator_arg_t, const Alloc&, Types...)" | ||
| "or (Types..., const Alloc&) if uses_allocator_v<T, Alloc> is true"); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| template <class _Ty, class _Alloc, class _Tuple1, class _Tuple2, enable_if_t<_Is_specialization_v<_Ty, pair>, int> = 0> | ||
| constexpr auto uses_allocator_construction_args( | ||
| const _Alloc& _Al, piecewise_construct_t, _Tuple1&& _Tup1, _Tuple2&& _Tup2) noexcept { | ||
| return _STD make_tuple(piecewise_construct, | ||
| _STD apply( | ||
| [&_Al](auto&&... _Tuple_args) { | ||
| return uses_allocator_construction_args<typename _Ty::first_type>( | ||
| _Al, _STD forward<decltype(_Tuple_args)>(_Tuple_args)...); | ||
| }, | ||
| _STD forward<_Tuple1>(_Tup1)), | ||
| _STD apply( | ||
| [&_Al](auto&&... _Tuple_args) { | ||
| return uses_allocator_construction_args<typename _Ty::second_type>( | ||
| _Al, _STD forward<decltype(_Tuple_args)>(_Tuple_args)...); | ||
| }, | ||
| _STD forward<_Tuple2>(_Tup2))); | ||
| } | ||
|
|
||
| template <class _Ty, class _Alloc, enable_if_t<_Is_specialization_v<_Ty, pair>, int> = 0> | ||
| constexpr auto uses_allocator_construction_args(const _Alloc& _Al) noexcept { | ||
| // equivalent to | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are you not returning whats the equivalent call? This applies to all functions. As I can see it it involves more function calls.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't it good to have less function template instantiations? And no, it involves one less |
||
| // return uses_allocator_construction_args<_Ty>(_Al, piecewise_construct, tuple<>(), tuple<>()); | ||
| return _STD make_tuple(piecewise_construct, uses_allocator_construction_args<typename _Ty::first_type>(_Al), | ||
| uses_allocator_construction_args<typename _Ty::second_type>(_Al)); | ||
| } | ||
|
|
||
| template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_specialization_v<_Ty, pair>, int> = 0> | ||
| constexpr auto uses_allocator_construction_args(const _Alloc& _Al, _Uty1&& _Val1, _Uty2&& _Val2) noexcept { | ||
| // equivalent to | ||
| // return uses_allocator_construction_args<_Ty>(_Al, piecewise_construct, | ||
| // _STD forward_as_tuple(_STD forward<_Uty1>(_Val1)), _STD forward_as_tuple(_STD forward<_Uty2>(_Val2))); | ||
| return _STD make_tuple(piecewise_construct, | ||
| uses_allocator_construction_args<typename _Ty::first_type>(_Al, _STD forward<_Uty1>(_Val1)), | ||
| uses_allocator_construction_args<typename _Ty::second_type>(_Al, _STD forward<_Uty2>(_Val2))); | ||
| } | ||
|
|
||
| template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_specialization_v<_Ty, pair>, int> = 0> | ||
| constexpr auto uses_allocator_construction_args(const _Alloc& _Al, const pair<_Uty1, _Uty2>& _Pair) noexcept { | ||
| // equivalent to | ||
| // return uses_allocator_construction_args<_Ty>(_Al, piecewise_construct, | ||
| // _STD forward_as_tuple(pr.first), _STD forward_as_tuple(pr.second)); | ||
| return _STD make_tuple(piecewise_construct, | ||
| uses_allocator_construction_args<typename _Ty::first_type>(_Al, _Pair.first), | ||
| uses_allocator_construction_args<typename _Ty::second_type>(_Al, _Pair.second)); | ||
| } | ||
|
|
||
| template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_specialization_v<_Ty, pair>, int> = 0> | ||
| constexpr auto uses_allocator_construction_args(const _Alloc& _Al, pair<_Uty1, _Uty2>&& _Pair) noexcept { | ||
| // equivalent to | ||
| // return uses_allocator_construction_args<_Ty>(_Al, piecewise_construct, | ||
| // _STD forward_as_tuple(_STD move(pr).first), _STD forward_as_tuple(_STD move(pr).second)); | ||
| return _STD make_tuple(piecewise_construct, | ||
| uses_allocator_construction_args<typename _Ty::first_type>(_Al, _STD move(_Pair).first), | ||
| uses_allocator_construction_args<typename _Ty::second_type>(_Al, _STD move(_Pair).second)); | ||
| } | ||
|
|
||
| template <class _Ty, class _Alloc, class... _Types> | ||
| constexpr _Ty make_obj_using_allocator(const _Alloc& _Al, _Types&&... _Args) { | ||
| return _STD make_from_tuple<_Ty>(uses_allocator_construction_args<_Ty>(_Al, _STD forward<_Types>(_Args)...)); | ||
| } | ||
|
|
||
| template <class _Ty, class _Alloc, class... _Types> | ||
| constexpr _Ty* uninitialized_construct_using_allocator(_Ty* _Ptr, const _Alloc& _Al, _Types&&... _Args) { | ||
| return ::new (static_cast<void*>(_Ptr)) _Ty(make_obj_using_allocator<_Ty>(_Al, _STD forward<_Types>(_Args)...)); | ||
| } | ||
|
|
||
| #endif // _HAS_CXX20 | ||
|
|
||
| _STD_END | ||
|
|
||
| #pragma pop_macro("new") | ||
|
|
||
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.
Maybe I am blind but arent thesetwo lines identical`?
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.
#ifpart changed, as in standard, in terms ofuses_allocator_construction_args