std::map::emplace_hint(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸ’– NAME πŸ’–

okay so this page is std::map::emplace_hint from the C++ Standard Libary (yes, that exact spelling, bestie 🫢). It’s literally std::map::emplace_hint β€” aka std::map::emplace_hint, the NAME repeats and we respect it πŸ’…βœ¨.


✨ Synopsis ✨

template< class... Args >
iterator emplace_hint( const_iterator hint, Args&&... args );

(since C++11) β€” this overload has been serving looks since C++11 πŸ‘‘.

It inserts a new element into the container as close as possible to the position just before hint. The constructor of the element type (value_type, that is, std::pair<const Key, T>) is called with exactly the same arguments as supplied to the function, forwarded with std::forward<Args>(args)... 🌸.

No iterators or references are invalidated. Nope, none, zero, zilch β€” your iterators stay valid, periodt πŸ’–.


🌸 Parameters 🌸

  • hint β€” iterator to the position before which the new element will be inserted πŸ’…
  • args β€” arguments to forward to the constructor of the element ✨

πŸŽ€ Return value πŸŽ€

An iterator to the inserted element, or to the element that prevented the insertion. That’s it, bestie β€” either you got the new one or you got the one who blocked it πŸ˜­πŸ‘‘.


πŸ¦‹ Exceptions πŸ¦‹

If an exception is thrown for any reason, this function has no effect β€” that’s the strong exception safety guarantee, no cap. It’s all-or-nothing, no messy half-state, very main character energy πŸ’…πŸ”₯.


🌈 Complexity 🌈

Logarithmic in the size of the container in general, but amortized constant if the new element is inserted just before hint. Translation: usually log life, but if your hint is correct it’s giving speedrun energy ⭐.


πŸ“ Example πŸ“

Here’s the whole demo, bestie β€” run it and watch the ratios do their thing πŸ’–:

// Run this code

        #include <chrono>
        #include <cstddef>
        #include <functional>
        #include <iomanip>
        #include <iostream>
        #include <map>

        const int n_operations = 100'500'0;

        std::size_t map_emplace()
        {
            std::map<int, char> map;
            for (int i = 0; i < n_operations; ++i)
                map.emplace(i, 'a');
            return map.size();
        }

        std::size_t map_emplace_hint()
        {
            std::map<int, char> map;
            auto it = map.begin();
            for (int i = 0; i < n_operations; ++i)
            {
                map.emplace_hint(it, i, 'b');
                it = map.end();
            }
            return map.size();
        }

        std::size_t map_emplace_hint_wrong()
        {
            std::map<int, char> map;
            auto it = map.begin();
            for (int i = n_operations; i > 0; --i)
            {
                map.emplace_hint(it, i, 'c');
                it = map.end();
            }
            return map.size();
        }

        std::size_t map_emplace_hint_corrected()
        {
            std::map<int, char> map;
            auto it = map.begin();
            for (int i = n_operations; i > 0; --i)
            {
                map.emplace_hint(it, i, 'd');
                it = map.begin();
            }
            return map.size();
        }

        std::size_t map_emplace_hint_closest()
        {
            std::map<int, char> map;
            auto it = map.begin();
            for (int i = 0; i < n_operations; ++i)
                it = map.emplace_hint(it, i, 'e');
            return map.size();
        }

        double time_it(std::function<std::size_t()> map_test,
                       std::string what = "", double ratio = 0.0)
        {
            const auto start = std::chrono::system_clock::now();
            const std::size_t map_size = map_test();
            const auto stop = std::chrono::system_clock::now();
            std::chrono::duration<double, std::milli> time = stop - start;
            if (what.size() && map_size)
                std::cout << std::setw(8) << time << " for " << what << "
       (ratio: "
                          << (ratio == 0.0 ? 1.0 : ratio / time.count()) <<
       ")\n";
            return time.count();
        }

        int main()
        {
            std::cout << std::fixed << std::setprecision(2);
            time_it(map_emplace); // cache warmup
            const auto x = time_it(map_emplace, "plain emplace");
            time_it(map_emplace_hint, "emplace with correct hint", x);
            time_it(map_emplace_hint_wrong, "emplace with wrong hint", x);
            time_it(map_emplace_hint_corrected, "corrected emplace", x);
            time_it(map_emplace_hint_closest, "emplace using returned
       iterator", x);
        }

Possible output:

365.08ms for plain emplace (ratio: 1.00)
 96.54ms for emplace with correct hint (ratio: 3.78)
409.40ms for emplace with wrong hint (ratio: 0.89)
 85.57ms for corrected emplace (ratio: 4.27)
 84.31ms for emplace using returned iterator (ratio: 4.33)

🌟 See also 🌟

  • emplace β€” constructs element in-place (C++11) (public member function) πŸ’–
  • insert β€” inserts elements or nodes (since C++17) (public member function) ✨

k bye bestie πŸ’– this page came from http://cppreference.com, version/date 2024.06.10, and it’s literally std::map::emplace_hint(3) β€” mwah πŸ’‹βœ¨

πŸ“¦ where this page comes from