From: Jonathan Wakely Date: Fri, 14 Oct 2016 16:12:21 +0000 (+0100) Subject: Avoid copies in std::scoped_allocator_adaptor piecewise construction X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a4744f620f32b6b859a39c6876f5e21b52b1af4b;p=gcc.git Avoid copies in std::scoped_allocator_adaptor piecewise construction * include/std/scoped_allocator (scoped_allocator_adaptor): Forward piecewise construction arguments as tuples of references, to avoid copies (related to LWG 2511). * testsuite/20_util/scoped_allocator/construct_pair.cc: New test. From-SVN: r241169 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index a87971f9fe8..7a3fdaf29f1 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,10 @@ +2016-10-14 Jonathan Wakely + + * include/std/scoped_allocator (scoped_allocator_adaptor): Forward + piecewise construction arguments as tuples of references, to avoid + copies (related to LWG 2511). + * testsuite/20_util/scoped_allocator/construct_pair.cc: New test. + 2016-10-14 Paolo Carlini * testsuite/26_numerics/accumulate/1.cc: Remove 'test' variables. diff --git a/libstdc++-v3/include/std/scoped_allocator b/libstdc++-v3/include/std/scoped_allocator index 39762fe444d..dcb97df63b3 100644 --- a/libstdc++-v3/include/std/scoped_allocator +++ b/libstdc++-v3/include/std/scoped_allocator @@ -369,10 +369,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION = __use_alloc<_T1, inner_allocator_type, _Args1...>(__inner); auto __y_use_tag = __use_alloc<_T2, inner_allocator_type, _Args2...>(__inner); + typename _Build_index_tuple::__type __x_indices; + typename _Build_index_tuple::__type __y_indices; typedef __outermost_alloc_traits _O_traits; _O_traits::construct(__outermost(*this), __p, piecewise_construct, - _M_construct_p(__x_use_tag, __x), - _M_construct_p(__y_use_tag, __y)); + _M_construct_p(__x_use_tag, __x_indices, __x), + _M_construct_p(__y_use_tag, __y_indices, __y)); } template @@ -428,26 +430,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept; private: - template - _Tuple&& - _M_construct_p(__uses_alloc0, _Tuple& __t) + template + tuple<_Args&&...> + _M_construct_p(__uses_alloc0, _Ind, tuple<_Args...>& __t) { return std::move(__t); } - template - std::tuple - _M_construct_p(__uses_alloc1_, std::tuple<_Args...>& __t) + template + tuple + _M_construct_p(__uses_alloc1_, _Index_tuple<_Ind...>, + tuple<_Args...>& __t) { - typedef std::tuple _Tuple; - return std::tuple_cat(_Tuple(allocator_arg, inner_allocator()), - std::move(__t)); + return { allocator_arg, inner_allocator(), + std::get<_Ind>(std::move(__t))... + }; } - template - std::tuple<_Args..., inner_allocator_type&> - _M_construct_p(__uses_alloc2_, std::tuple<_Args...>& __t) + template + tuple<_Args&&..., inner_allocator_type&> + _M_construct_p(__uses_alloc2_, _Index_tuple<_Ind...>, + tuple<_Args...>& __t) { - typedef std::tuple _Tuple; - return std::tuple_cat(std::move(__t), _Tuple(inner_allocator())); + return { std::get<_Ind>(std::move(__t))..., inner_allocator() }; } }; diff --git a/libstdc++-v3/testsuite/20_util/scoped_allocator/construct_pair.cc b/libstdc++-v3/testsuite/20_util/scoped_allocator/construct_pair.cc new file mode 100644 index 00000000000..2996412a674 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/scoped_allocator/construct_pair.cc @@ -0,0 +1,81 @@ +// Copyright (C) 2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-do run { target c++11 } } + +#include +#include +#include + +struct do_not_copy { + do_not_copy() = default; + do_not_copy(const do_not_copy&) { throw 1; } +}; + +void +test01() +{ + struct X { + X(do_not_copy&&) { } + }; + + using pair = std::pair; + std::scoped_allocator_adaptor> a; + auto ptr = a.allocate(1); + a.construct(ptr, std::piecewise_construct, + std::tuple{}, std::make_tuple(1)); + a.deallocate(ptr, 1); +} + +void +test02() +{ + struct X { + using allocator_type = std::allocator; + X(do_not_copy&&, const allocator_type&) { } + }; + + using pair = std::pair; + std::scoped_allocator_adaptor> a; + auto ptr = a.allocate(1); + a.construct(ptr, std::piecewise_construct, + std::tuple{}, std::make_tuple(1)); + a.deallocate(ptr, 1); +} + +void +test03() +{ + struct X { + using allocator_type = std::allocator; + X(std::allocator_arg_t, const allocator_type&, do_not_copy&&) { } + }; + + using pair = std::pair; + std::scoped_allocator_adaptor> a; + auto ptr = a.allocate(1); + a.construct(ptr, std::piecewise_construct, + std::tuple{}, std::make_tuple(1)); + a.deallocate(ptr, 1); +} + +int main() +{ + test01(); + test02(); + test03(); +}