gcc/libstdc++-v3/include/bits
Jonathan Wakely db5fa0837e libstdc++: Avoid unnecessary allocations in std::map insertions [PR92300]
Inserting a pair<Key, Value> into a map<Key, Value> will allocate a new
node and construct a pair<const Key, Value> in the node, then check if
the Key is already present in the map. That is because pair<Key, Value>
is not the same type as the map's value_type. But it only differs in the
const-qualification on the Key, and so we should be able to do the
lookup directly, without allocating a new node. This avoids allocating
and then deallocating a node for the case where the key is already found
and nothing gets inserted.

We can take this optimization further and lookup the key directly for a
pair<Key, X>, pair<const Key, X>, pair<Key&, X> etc. for any X. A strict
reading of the standard says we can only do this when we know the
allocator won't do anything funky with the value when constructing a
pair<const Key, Value> from a slightly different type. Inserting that
type only requires the value_type to be Cpp17EmplaceInsertable into the
container, and that doesn't have any requirement that the value is
unchanged (unlike Cpp17CopyInsertable and Cpp17MoveInsertable). For that
reason, the optimization is only done for maps using std::allocator.

A similar optimization can be done for map.emplace(key, value) where the
first argument is similar to the key_type and so can be looked up
without allocating a new node and constructing a key_type.

Finally, both of the insert and emplace cases can use the same
optimization when key_type is a scalar type and some other scalar is
being passed as the insert/emplace argument. Converting from one scalar
type to another won't have surprising value-altering behaviour, and has
no side effects (unlike e.g. constructing a std::string from a const
char* argument, which might allocate).

We don't need to do this for std::multimap, because we always insert the
new node even if the key is already present. So there's no benefit to
doing the lookup before allocating the new node.

libstdc++-v3/ChangeLog:

	PR libstdc++/92300
	* include/bits/stl_map.h (insert(Pair&&), emplace(Args&&...)):
	Check whether the arguments can be looked up directly without
	constructing a temporary node first.
	* include/bits/stl_pair.h (__is_pair): Move to here, from ...
	* include/bits/uses_allocator_args.h (__is_pair): ... here.
	* testsuite/23_containers/map/modifiers/emplace/92300.cc: New test.
	* testsuite/23_containers/map/modifiers/insert/92300.cc: New test.
2021-12-09 22:56:57 +00:00
..
algorithmfwd.h
align.h
alloc_traits.h libstdc++: Implement constexpr std::vector for C++20 2021-11-12 00:42:39 +00:00
allocated_ptr.h
allocator.h libstdc++: Define std::__is_constant_evaluated() for internal use 2021-12-01 15:00:33 +00:00
atomic_base.h
atomic_futex.h
atomic_timed_wait.h
atomic_wait.h
basic_ios.h
basic_ios.tcc
basic_string.h libstdc++: Define std::__is_constant_evaluated() for internal use 2021-12-01 15:00:33 +00:00
basic_string.tcc libstdc++: Define std::__is_constant_evaluated() for internal use 2021-12-01 15:00:33 +00:00
boost_concept_check.h
c++0x_warning.h
c++config libstdc++: Skip atomic instructions in shared_ptr when both counts are 1 2021-12-08 11:39:34 +00:00
char_traits.h libstdc++: Disable over-zealous warnings about std::string copies [PR103332] 2021-12-09 22:51:06 +00:00
charconv.h
chrono.h
codecvt.h
concept_check.h
cow_string.h libstdc++: Do not leak empty COW strings 2021-12-09 22:51:06 +00:00
cpp_type_traits.h
deque.tcc
enable_special_members.h
erase_if.h libstdc++: [_GLIBCXX_DEBUG] Reduce performance impact on std::erase_if 2021-11-20 16:11:22 +01:00
forward_list.h
forward_list.tcc
fs_dir.h
fs_fwd.h
fs_ops.h
fs_path.h
fstream.tcc
functexcept.h
functional_hash.h
gslice_array.h
gslice.h
hashtable_policy.h libstdc++: Unordered containers merge re-use hash code 2021-11-15 18:52:07 +01:00
hashtable.h libstdc++: Unordered containers merge re-use hash code 2021-11-15 18:52:07 +01:00
indirect_array.h
invoke.h
ios_base.h
istream.tcc
iterator_concepts.h
list.tcc
locale_classes.h
locale_classes.tcc
locale_conv.h
locale_facets_nonio.h
locale_facets_nonio.tcc
locale_facets.h
locale_facets.tcc
localefwd.h
mask_array.h
max_size_type.h
memoryfwd.h
mofunc_impl.h
move_only_function.h
move.h
new_allocator.h libstdc++: Fix non-reserved name in std::allocator base class [PR64135] 2021-12-09 22:50:10 +00:00
node_handle.h
ostream_insert.h
ostream.tcc
parse_numbers.h
postypes.h
predefined_ops.h
ptr_traits.h libstdc++: Make std::pointer_traits SFINAE-friendly [PR96416] 2021-11-25 23:12:14 +00:00
quoted_string.h
random.h
random.tcc
range_access.h
ranges_algo.h
ranges_algobase.h libstdc++: Define std::__is_constant_evaluated() for internal use 2021-12-01 15:00:33 +00:00
ranges_base.h
ranges_cmp.h libstdc++: Define std::__is_constant_evaluated() for internal use 2021-12-01 15:00:33 +00:00
ranges_uninitialized.h
ranges_util.h
refwrap.h
regex_automaton.h
regex_automaton.tcc
regex_compiler.h
regex_compiler.tcc
regex_constants.h
regex_error.h
regex_executor.h
regex_executor.tcc
regex_scanner.h
regex_scanner.tcc
regex.h libstdc++: Initialize member in std::match_results [PR103549] 2021-12-04 15:55:01 +00:00
regex.tcc
semaphore_base.h
shared_ptr_atomic.h
shared_ptr_base.h libstdc++: Fix undefined shift when _Atomic_word is 64-bit 2021-12-08 23:41:03 +00:00
shared_ptr.h
slice_array.h
specfun.h
sstream.tcc
std_abs.h
std_function.h
std_mutex.h
std_thread.h
stl_algo.h
stl_algobase.h libstdc++: Define std::__is_constant_evaluated() for internal use 2021-12-01 15:00:33 +00:00
stl_bvector.h libstdc++: Define std::__is_constant_evaluated() for internal use 2021-12-01 15:00:33 +00:00
stl_construct.h libstdc++: Define std::__is_constant_evaluated() for internal use 2021-12-01 15:00:33 +00:00
stl_deque.h
stl_function.h libstdc++: Define std::__is_constant_evaluated() for internal use 2021-12-01 15:00:33 +00:00
stl_heap.h
stl_iterator_base_funcs.h
stl_iterator_base_types.h
stl_iterator.h
stl_list.h
stl_map.h libstdc++: Avoid unnecessary allocations in std::map insertions [PR92300] 2021-12-09 22:56:57 +00:00
stl_multimap.h
stl_multiset.h
stl_numeric.h
stl_pair.h libstdc++: Avoid unnecessary allocations in std::map insertions [PR92300] 2021-12-09 22:56:57 +00:00
stl_queue.h
stl_raw_storage_iter.h
stl_relops.h
stl_set.h
stl_stack.h
stl_tempbuf.h
stl_tree.h libstdc++: Simplify emplace member functions in _Rb_tree 2021-12-03 22:52:27 +00:00
stl_uninitialized.h libstdc++: Fix trivial relocation for constexpr std::vector 2021-11-26 22:28:48 +00:00
stl_vector.h libstdc++: Define std::__is_constant_evaluated() for internal use 2021-12-01 15:00:33 +00:00
stream_iterator.h
streambuf_iterator.h
streambuf.tcc
string_view.tcc
stringfwd.h
this_thread_sleep.h
uniform_int_dist.h
unique_lock.h
unique_ptr.h
unordered_map.h
unordered_set.h
uses_allocator_args.h libstdc++: Avoid unnecessary allocations in std::map insertions [PR92300] 2021-12-09 22:56:57 +00:00
uses_allocator.h
utility.h
valarray_after.h
valarray_array.h
valarray_array.tcc
valarray_before.h
vector.tcc libstdc++: Implement constexpr std::vector for C++20 2021-11-12 00:42:39 +00:00