std::map::insert_or_assign(3)
π std::map::insert_or_assign β from the C++ Standard Library, bestie
okay so first things first: the manual name is std::map::insert_or_assign(3), from the C++ Standard Library, and this whole page is about one little member function that just gets you. No cap.
β¨ NAME β¨
std::map::insert_or_assign β literally what it says on the tin: it inserts a thing, or it assigns a thing. Iconic behavior. We stan a function that communicates.
π¦ Synopsis π¦
Six whole overloads, and yes we're listing every single one, because missing an overload is not the vibe.
(1) (since C++17)
template< class M >
std::pair<iterator, bool> insert_or_assign( const Key& k, M&& obj );
(2) (since C++17)
template< class M >
std::pair<iterator, bool> insert_or_assign( Key&& k, M&& obj );
(3) (since C++26)
template< class K, class M >
std::pair<iterator, bool> insert_or_assign( K&& k, M&& obj );
(4) (since C++17)
template< class M >
iterator insert_or_assign( const_iterator hint, const Key& k, M&& obj );
(5) (since C++17)
template< class M >
iterator insert_or_assign( const_iterator hint, Key&& k, M&& obj );
(6) (since C++26)
template< class K, class M >
iterator insert_or_assign( const_iterator hint, K&& k, M&& obj );
Now the glow-up explanation of what each group actually does π
- 1 and 4 β if a key equivalent to
kalready exists in the container, it assignsstd::forward<M>(obj)to themapped_typecorresponding to the keyk. If the key does not exist, it inserts the new value as if byinsert, constructing it fromvalue_type(k, std::forward<M>(obj)). - 2 and 5 β same as (1,4), except the mapped value is constructed from
value_type(std::move(k), std::forward<M>(obj)). - 3 and 6 β if a key equivalent to
kalready exists in the container, it assignsstd::forward<M>(obj)to themapped_typecorresponding to the keyk. If the key does not exist, it constructs an objectuofvalue_typewithstd::forward<K>(k),std::forward<M>(obj)), then insertsuinto*this. β οΈ Ifequal_range(u.first) == equal_range(k)is false, the behavior is undefined. Thevalue_typemust beEmplaceConstructibleintomapfromstd::forward<K>(k),std::forward<M>(obj). This overload participates in overload resolution only if the qualified-idCompare::is_transparentis valid and denotes a type. It allows calling this function without constructing an instance ofKey. (iykyk β that's the hetero lookups club π«Ά)
π¨ important vibe check: if std::is_assignable_v<mapped_type&, M&&> is false, then the behavior is undefined (until C++20), and the program is ill-formed (since C++20). Like, don't do that. Please.
β¨ And the best part: no iterators or references are invalidated. She's polite. She doesn't disturb the neighbors.
π Parameters π
kβ the key used both to look up and to insert if not found. Dual-purpose queen πhintβ iterator to the position before which the new element will be insertedobjβ the value to insert or assign
π Return value π
- 1-3) The
boolcomponent istrueif the insertion took place andfalseif the assignment took place. The iterator component is pointing at the element that was inserted or updated. - 4-6) Iterator pointing at the element that was inserted or updated.
So basically overloads 1β3 give you the receipt and the location π, and 4β6 just point at the thing.
πΈ Complexity πΈ
- 1-3) Same as for
emplace. - 4-6) Same as for
emplace_hint.
π Notes π
insert_or_assign returns more information than operator[] and does not require default-constructibility of the mapped type. That's the whole flex. It tells you what happened and it doesn't force your mapped type to be default-constructible. main character energy, honestly.
Feature-test macro tea β:
__cpp_lib_map_try_emplaceβ value201411L, std(C++17)β coversstd::map::try_emplace,std::map::insert_or_assign, Heterogeneous overloads for the remaining member functions in ordered and unordered associative containers.__cpp_lib_associative_heterogeneous_insertionβ value202311L, std(C++26)β covers Heterogeneous overloads for the remaining member functions in ordered and unordered associative containers. Overloads (3) and (6).
π§ Example π§
(// Run this code)
#include <iostream>
#include <string>
#include <map>
void print_node(const auto& node)
{
std::cout << '[' << node.first << "] = " << node.second << '\n';
}
void print_result(auto const& pair)
{
std::cout << (pair.second ? "inserted: " : "assigned: ");
print_node(*pair.first);
}
int main()
{
std::map<std::string, std::string> myMap;
print_result(myMap.insert_or_assign("a", "apple"));
print_result(myMap.insert_or_assign("b", "banana"));
print_result(myMap.insert_or_assign("c", "cherry"));
print_result(myMap.insert_or_assign("c", "clementine"));
for (const auto& node : myMap)
print_node(node);
}
Output:
inserted: [a] = apple
inserted: [b] = banana
inserted: [c] = cherry
assigned: [c] = clementine
[a] = apple
[b] = banana
[c] = clementine
See how "c" got inserted once and then assigned the second time? That's the whole point, bestie. Cherry β‘οΈ clementine. Growth. π
β See also β
operator[]β access or insert specified element (public member function)atβ access specified element with bounds checking (public member function)insertβ inserts elements or nodes (since C++17) (public member function)emplace(C++11) β constructs element in-place (public member function)
π one last thing: that hint overload set is not a do-nothing parameter β it's "iterator to the position before which the new element will be inserted." Read it. Respect it. π«Ά
okay bye ily, go insert_or_assign something π
source: cppreference.com Β· version: 2024.06.10 β mwah, that's the footer tea, see u next manpage πβ¨
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms