aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/include/std
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2025-04-04 15:05:09 -0400
committerPatrick Palka <ppalka@redhat.com>2025-04-04 15:05:09 -0400
commit2a36d22ab52d6ffce9a1fcaf7aca83336679e111 (patch)
tree1a7e785a74125a42ff6881802eed3e7708dc8e44 /libstdc++-v3/include/std
parentd25728c98682c058bfda79333c94b0a8cf2a3f49 (diff)
downloadgcc-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_set20
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)