Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions stl/inc/scoped_allocator
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,16 @@ public:

template <class _Ty, class... _Types>
void construct(_Ty* _Ptr, _Types&&... _Args) { // construct with varying allocator styles
#if _HAS_CXX20
_STD apply(
[_Ptr, this](auto&&... _New_args) {
_Scoped_outermost_traits<scoped_allocator_adaptor>::construct(
_Scoped_outermost(*this), _Ptr, _STD forward<decltype(_New_args)>(_New_args)...);
},
uses_allocator_construction_args<_Ty>(inner_allocator(), _STD forward<_Types>(_Args)...));
#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv
_Uses_allocator_construct(_Ptr, _Scoped_outermost(*this), inner_allocator(), _STD forward<_Types>(_Args)...);
Copy link
Contributor

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`?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#if part changed, as in standard, in terms of uses_allocator_construction_args

#endif
}

template <class _Ty>
Expand Down
96 changes: 96 additions & 0 deletions stl/inc/xmemory
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Contributor Author

@ArtemSarmini ArtemSarmini Jan 16, 2020

Choose a reason for hiding this comment

The 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 uses_allocator_construction_args and 2 apply calls in all cases

// 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")
Expand Down
4 changes: 4 additions & 0 deletions stl/inc/xpolymorphic_allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ void _Uses_allocator_construct(_Ty* const _Ptr, _Outer_alloc& _Outer, _Inner_all
_STD forward<_Types>(_Args)...); // TRANSITION, if constexpr
}

#if !_HAS_CXX20

template <class _Alloc, class... _Types>
auto _Uses_allocator_piecewise2(true_type, _Alloc& _Al, tuple<_Types...>&& _Tuple) {
return _STD tuple_cat(tuple<allocator_arg_t, _Alloc&>(allocator_arg, _Al), _STD move(_Tuple));
Expand Down Expand Up @@ -134,6 +136,8 @@ void _Uses_allocator_construct(
_STD forward_as_tuple(_STD forward<_Vty>(_Pair.second)));
}

#endif // !_HAS_CXX20

#if _HAS_CXX17
namespace pmr {

Expand Down
2 changes: 2 additions & 0 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,15 @@
// P0457R2 starts_with()/ends_with() For basic_string/basic_string_view
// P0458R2 contains() For Ordered And Unordered Associative Containers
// P0463R1 endian
// P0475R1 Guaranteed Copy Elision For Piecewise Construction
// P0482R6 Library Support For char8_t
// (mbrtoc8 and c8rtomb not yet implemented)
// P0487R1 Fixing operator>>(basic_istream&, CharT*)
// P0550R2 remove_cvref
// P0553R4 <bit> Rotating And Counting Functions
// P0556R3 <bit> ispow2(), ceil2(), floor2(), log2p1()
// (log2p1() is called bit_length() as of D1956)
// P0591R4 Utility Functions For Uses-Allocator Construction
// P0595R2 is_constant_evaluated()
// P0616R0 Using move() In <numeric>
// P0631R8 <numbers> Math Constants
Expand Down