[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