diff options
author | Patrick Palka <ppalka@redhat.com> | 2025-04-04 15:05:09 -0400 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2025-04-04 15:05:09 -0400 |
commit | 2a36d22ab52d6ffce9a1fcaf7aca83336679e111 (patch) | |
tree | 1a7e785a74125a42ff6881802eed3e7708dc8e44 /libstdc++-v3/include/std | |
parent | d25728c98682c058bfda79333c94b0a8cf2a3f49 (diff) | |
download | gcc-2a36d22ab52d6ffce9a1fcaf7aca83336679e111.zip gcc-2a36d22ab52d6ffce9a1fcaf7aca83336679e111.tar.gz gcc-2a36d22ab52d6ffce9a1fcaf7aca83336679e111.tar.bz2 |
libstdc++: Avoid redundant value_type object in flat_set::emplace [PR119620]
flat_set::emplace (and flat_multiset's) currently unconditionally
constructs an object outside of the container, but if we're passed
a value_type object we can and should avoid that.
PR libstdc++/119620
libstdc++-v3/ChangeLog:
* include/std/flat_set (_Flat_set_impl::_M_try_emplace): Split
out into two overloads, one taking at least one argument and one
taking zero arguments. Turn __k into an auto&& reference bound
to __arg if it's already a value_type and otherwise bound to a
lifetime-extended value_type temporary.
* testsuite/23_containers/flat_multiset/1.cc (test08): New test.
* testsuite/23_containers/flat_set/1.cc (test08): New test.
Reviewed-by: Tomasz KamiĆski <tkaminsk@redhat.com>
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Diffstat (limited to 'libstdc++-v3/include/std')
-rw-r--r-- | libstdc++-v3/include/std/flat_set | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/libstdc++-v3/include/std/flat_set b/libstdc++-v3/include/std/flat_set index a7b0b8a..3e15d1a 100644 --- a/libstdc++-v3/include/std/flat_set +++ b/libstdc++-v3/include/std/flat_set @@ -350,12 +350,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return _M_cont.max_size(); } // modifiers - template<typename... _Args> + template<typename _Arg, typename... _Args> pair<iterator, bool> - _M_try_emplace(optional<const_iterator> __hint, _Args&&... __args) + _M_try_emplace(optional<const_iterator> __hint, _Arg&& __arg, _Args&&... __args) { // TODO: Simplify and audit the hint handling. - value_type __k(std::forward<_Args>(__args)...); + auto&& __k = [&] -> decltype(auto) { + if constexpr (sizeof...(_Args) == 0 + && same_as<remove_cvref_t<_Arg>, value_type>) + return std::forward<_Arg>(__arg); + else + return value_type(std::forward<_Arg>(__arg), + std::forward<_Args>(__args)...); + }(); typename container_type::iterator __it; int __r = -1, __s = -1; if (__hint.has_value() @@ -397,12 +404,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return {__it, false}; auto __guard = _M_make_clear_guard(); - __it = _M_cont.insert(__it, std::move(__k)); + __it = _M_cont.insert(__it, std::forward<decltype(__k)>(__k)); __guard._M_disable(); return {__it, true}; } template<typename... _Args> + pair<iterator, bool> + _M_try_emplace(optional<const_iterator> __hint) + { return _M_try_emplace(__hint, value_type()); } + + template<typename... _Args> requires is_constructible_v<value_type, _Args...> __emplace_result_t emplace(_Args&&... __args) |