[PATCH] C++2a Utility functions to implement uses-allocator construction (P0591R4)
Jonathan Wakely
jwakely@redhat.com
Mon Mar 4 09:23:00 GMT 2019
On 04/03/19 09:14 +0000, Jonathan Wakely wrote:
>On 01/03/19 14:06 +0000, Jonathan Wakely wrote:
>>On 01/03/19 13:50 +0000, Jonathan Wakely wrote:
>>> * include/std/memory (uses_allocator_construction_args): New set of
>>> overloaded functions.
>>> (make_obj_using_allocator, uninitialized_construct_using_allocator):
>>> New functions.
>>> * include/std/memory_resource (polymorphic_allocator::construct)
>>> [__cplusplus > 201703l]: Replace all overloads with a single function
>>> using uses_allocator_construction_args.
>>> * testsuite/20_util/polymorphic_allocator/construct_c++2a.cc: New
>>> test.
>>> * testsuite/20_util/uses_allocator/make_obj.cc: New test.
>>
>>If we don't care about providing the exact signatures from the C++2a
>>draft, we could do this and use it in C++17 as well ...
>
>[...]
>
>>+ if constexpr (sizeof...(__args) == 0)
>>+ {
>>+ return std::make_tuple(piecewise_construct,
>>+ std::__uses_alloc_args<_Tp1>(__a),
>>+ std::__uses_alloc_args<_Tp2>(__a));
>>+ }
>>+ else if constexpr (sizeof...(__args) == 1)
>>+ {
>>+ return std::make_tuple(piecewise_construct,
>>+ std::__uses_alloc_args<_Tp1>(__a,
>>+ std::forward<_Args>(__args).first...),
>>+ std::__uses_alloc_args<_Tp2>(__a,
>>+ std::forward<_Args>(__args).second...));
>>+ }
>>+ else if constexpr (sizeof...(__args) == 2)
>>+ {
>>+ return [&](auto&& __arg1, auto&& __arg2)
>>+ {
>>+ return std::make_tuple(piecewise_construct,
>>+ std::__uses_alloc_args<_Tp1>(__a,
>>+ std::forward<decltype(__arg1)>(__arg1)),
>>+ std::__uses_alloc_args<_Tp2>(__a,
>>+ std::forward<decltype(__arg2)>(__arg2)));
>>+ }(std::forward<_Args>(__args)...);
>>+ }
>
>I tried replacing this lambda with:
>
> using _Targs = tuple<_Args&&...>;
> _Targs __targs{std::forward<_Args>(__args)...};
>
> using _Args_0 = tuple_element_t<0, _Targs>;
> using _Args_1 = tuple_element_t<1, _Targs>;
>
> return std::make_tuple(piecewise_construct,
> std::__uses_alloc_args<_Tp1>(__a,
> std::forward<_Args_0>(std::get<0>(__targs))),
> std::__uses_alloc_args<_Tp2>(__a,
> std::forward<_Args_1>(std::get<1>(__targs))));
>
>And similarly for the sizeof...(__args))==3 case. Which seems more
>straightforward, unfortunately it compiles measurably slower, using
>more memory. The optimized code is the same size, but unoptimized the
>lambda version is a bit smaller.
>
>The current code on trunk compiles fastest, by quite a big margin.
>That surprises me as I thought a single function using if-constexpr
>would outperform several overloads constrained via SFINAE.
>
>Being able to use __uses_alloc_args in C++17 might be worth the extra
>compile-time cost though. I'll keep thinking about it.
In case anybody wants to try it out, here's the complete patch
(relative to r269312 on trunk) using std::get<N> to extract elements
from the pack, instead of using lambdas.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch.txt
Type: text/x-patch
Size: 14818 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20190304/6fbe438f/attachment.bin>
More information about the Gcc-patches
mailing list