Simplify common case of use_future_t that uses std::allocator

There is no need to store and pass around the allocator object when it's
an instance of std::allocator. Define a partial specialization of
std::use_future_t and the corresponding completion token so that no
allocator is stored. Overload the completion handler constructor to not
expect an allocator to be stored.

	* include/experimental/executor (__use_future_ct, use_future_t):
	Define partial specializations for std::allocator.
	(__use_future_ch): Overload constructor for completion tokens using
	std::allocator.

From-SVN: r277404
This commit is contained in:
Jonathan Wakely 2019-10-24 15:39:57 +01:00 committed by Jonathan Wakely
parent abebffc609
commit 5ce55f3ff5
2 changed files with 48 additions and 2 deletions

View File

@ -1,5 +1,10 @@
2019-10-24 Jonathan Wakely <jwakely@redhat.com>
* include/experimental/executor (__use_future_ct, use_future_t):
Define partial specializations for std::allocator.
(__use_future_ch): Overload constructor for completion tokens using
std::allocator.
PR libstdc++/88338 Implement P0898R3, C++20 concepts library
* doc/xml/manual/status_cxx2020.xml: Update status.
* doc/html/*: Regenerate.

View File

@ -1501,12 +1501,18 @@ inline namespace v1
std::tuple<_Func, _Alloc> _M_t;
};
template<typename _Func, typename _Tp>
struct __use_future_ct<_Func, std::allocator<_Tp>>
{
_Func _M_f;
};
template<typename _ProtoAllocator = allocator<void>>
class use_future_t
{
public:
// use_future_t types:
typedef _ProtoAllocator allocator_type;
using allocator_type = _ProtoAllocator;
// use_future_t members:
constexpr use_future_t() noexcept : _M_alloc() { }
@ -1514,7 +1520,7 @@ inline namespace v1
explicit
use_future_t(const _ProtoAllocator& __a) noexcept : _M_alloc(__a) { }
template<class _OtherAllocator>
template<typename _OtherAllocator>
use_future_t<_OtherAllocator>
rebind(const _OtherAllocator& __a) const noexcept
{ return use_future_t<_OtherAllocator>(__a); }
@ -1533,6 +1539,35 @@ inline namespace v1
_ProtoAllocator _M_alloc;
};
template<typename _Tp>
class use_future_t<std::allocator<_Tp>>
{
public:
// use_future_t types:
using allocator_type = std::allocator<_Tp>;
// use_future_t members:
constexpr use_future_t() noexcept = default;
explicit
use_future_t(const allocator_type& __a) noexcept { }
template<class _Up>
use_future_t<std::allocator<_Up>>
rebind(const std::allocator<_Up>& __a) const noexcept
{ return use_future_t<std::allocator<_Up>>(__a); }
allocator_type get_allocator() const noexcept { return {}; }
template<typename _Func>
auto
operator()(_Func&& __f) const
{
using _Token = __use_future_ct<decay_t<_Func>, allocator_type>;
return _Token{std::forward<_Func>(__f)};
}
};
constexpr use_future_t<> use_future = use_future_t<>();
template<typename _Func, typename _Alloc, typename _Res, typename... _Args>
@ -1552,6 +1587,12 @@ inline namespace v1
_M_promise{ std::get<1>(__token._M_t) }
{ }
template<typename _Tp>
explicit
__use_future_ch(__use_future_ct<_Func, std::allocator<_Tp>>&& __token)
: _M_f{ std::move(__token._M_f) }
{ }
void
operator()(_Args&&... __args)
{