3

Thanks to the good book C++17 in detail of Bartlomiej Filipek. I am discovering some examples which use insert in the context of std::map.

So I visited cppreference.com to have a better idea about how it works.

https://en.cppreference.com/w/cpp/container/map/insert

However, at the bottom of the page, there is a valuable and long example which gives us different examples of usage of std::map::insert. I have tested it by myself on my computer to try to understand why with overload 1 and overload 4, the insertion fails.

And honestly, I did not understand why.

I would grateful to you to explain what happens in those 2 specific examples (why the insertion fails), as it seems to be a very interesting example which uses at the same time the notion of "structured bindings".

#include <iomanip> #include <iostream> #include <map> #include <string> using namespace std::literals; template<typename It> void printInsertionStatus(It it, bool success) { std::cout << "Insertion of " << it->first << (success ? " succeeded\n" : " failed\n"); } int main() { std::map<std::string, float> karasunoPlayerHeights; // Overload 3: insert from rvalue reference const auto [it_hinata, success] = karasunoPlayerHeights.insert({ "Hinata"s, 162.8 }); printInsertionStatus(it_hinata, success); { // Overload 1: insert from lvalue reference const auto [it, success2] = karasunoPlayerHeights.insert(*it_hinata); printInsertionStatus(it, success2); } { // Overload 2: insert via forwarding to emplace const auto [it, success] = karasunoPlayerHeights.insert({ "Kageyama", 180.6 }); printInsertionStatus(it, success); } { // Overload 6: insert from rvalue reference with positional hint const std::size_t n = std::size(karasunoPlayerHeights); const auto it = karasunoPlayerHeights.insert(it_hinata, { "Azumane"s, 184.7 }); printInsertionStatus(it, std::size(karasunoPlayerHeights) != n); } { // Overload 4: insert from lvalue reference with positional hint const std::size_t n = std::size(karasunoPlayerHeights); const auto it = karasunoPlayerHeights.insert(it_hinata, *it_hinata); printInsertionStatus(it, std::size(karasunoPlayerHeights) != n); } { // Overload 5: insert via forwarding to emplace with positional hint const std::size_t n = std::size(karasunoPlayerHeights); const auto it = karasunoPlayerHeights.insert(it_hinata, { "Tsukishima", 188.3 }); printInsertionStatus(it, std::size(karasunoPlayerHeights) != n); } auto node_hinata = karasunoPlayerHeights.extract(it_hinata); std::map<std::string, float> playerHeights; // Overload 7: insert from iterator range playerHeights.insert(std::begin(karasunoPlayerHeights), std::end(karasunoPlayerHeights)); // Overload 8: insert from initializer_list playerHeights.insert({ {"Kozume"s, 169.2}, {"Kuroo", 187.7} }); // Overload 9: insert node const auto status = playerHeights.insert(std::move(node_hinata)); printInsertionStatus(status.position, status.inserted); node_hinata = playerHeights.extract(status.position); { // Overload 10: insert node with positional hint const std::size_t n = std::size(playerHeights); const auto it = playerHeights.insert(std::begin(playerHeights), std::move(node_hinata)); printInsertionStatus(it, std::size(playerHeights) != n); } // Print resulting map std::cout << std::left << '\n'; for (const auto& [name, height] : playerHeights) std::cout << std::setw(10) << name << " | " << height << "cm\n"; } 
9
  • 1
    Something's missing here. When you use hinted insert, you need a call to lower_bound to get that iterator. Commented Aug 9, 2019 at 21:41
  • 1
    can you show the complete code? - something seems to be missing. Commented Aug 9, 2019 at 21:43
  • I sent the complete code for you. Commented Aug 9, 2019 at 21:46
  • 1
    @D.K. "it seems to be a very interesting example which uses at the same time the notion of "structured bindings"." Keep in mind that, the question, has nothing to do with structured bindings here. Commented Aug 9, 2019 at 22:24
  • 1
    @D.K. It's kind of obsolete ever since C++17's insert_or_assign(), but there's an idiom when you use lower_bound() followed by a key comparison to do the equivalent of find(). Then, if it's not found, the iterator is used for the hinted insert. Commented Aug 11, 2019 at 1:03

1 Answer 1

2

As stated on the cppreference.com the std::map::insert:

Inserts element(s) into the container, if the container doesn't already contain an element with an equivalent key.

In // Overload 1:

The iterator it_hinata is pointing to the lastly inserted entry which is {"Hinata"s, 162.8} and if you try to enter the same key-value pair, the insertion fails and hence success2 == false.

In // Overload 4:

The iterator it_hinata is still pointing to the same (firstly) inserted key-value pair(i.e. same {"Hinata"s, 162.8}). Therefore, the same reason in the above case, insertion fails. That means, the size of the map(i.e. karasunoPlayerHeights) remains the same after the insertion call, and the condition std::size(karasunoPlayerHeights) != n evaluated to false.

Following is the minimal, complete reproducible example from what OP posted:

#include <iomanip> #include <iostream> #include <map> #include <string> using namespace std::literals; template<typename It> void printInsertionStatus(It it, bool success) { std::cout << "Insertion of " << it->first << (success ? " succeeded\n" : " failed\n"); } int main() { std::map<std::string, float> karasunoPlayerHeights; // Overload 3: insert from rvalue reference const auto [it_hinata, success] = karasunoPlayerHeights.insert({ "Hinata"s, 162.8f }); printInsertionStatus(it_hinata, success); { // Overload 1: insert from lvalue reference const auto [it, success2] = karasunoPlayerHeights.insert(*it_hinata); printInsertionStatus(it, success2); } { // Overload 4: insert from lvalue reference with positional hint const std::size_t n = std::size(karasunoPlayerHeights); const auto it = karasunoPlayerHeights.insert(it_hinata, *it_hinata); printInsertionStatus(it, std::size(karasunoPlayerHeights) != n); } // Print resulting map std::cout << std::left << '\n'; for (const auto& [name, height] : karasunoPlayerHeights) std::cout << std::setw(10) << name << " | " << height << "cm\n"; } 

which outputs:

Insertion of Hinata succeeded Insertion of Hinata failed Insertion of Hinata failed Hinata | 162.8cm 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.