kostasch
kostasch

Reputation: 25

Implementing efficient insertion on a custom unordered_map container in C++

I am creating a custom C++ STL Container library and I have a question that concerns efficient insertion both in code size and execution time (avoiding as many copies as possible).

I want to write an insert (same applies for find/erase) function (_insert_unique) that can be called from other insert-like functions and also preserve their semantics.

For example :

    std::pair<iterator, bool> insert(const value_type &val) {
        return _insert_unique(val);
    }

    std::pair<iterator, bool> insert(value_type &&val) {
        return _insert_unique(std::move(val));
    }

    template <class... Args>
    std::pair<iterator, bool> emplace(Args&&... args) {
       return _insert_unique(std::forward<Args>(args)...);
    }

By preserving the semantics I mean that this function should avoid making copies when the parameter is value_type&& or avoid constructing a key in emplace() if the key doesn't already exist in the set (I know that the C++11 emplace() version requires some workaround on this by using "forward_as_tuple" and "piecewise_construct" and that a new function try_emplace() was introduced afterwards for this purpose).

So my question is if I can achieve the functionality I want without writing duplicate code for every insert-like function.

Upvotes: 1

Views: 62

Answers (1)

G&#39;k
G&#39;k

Reputation: 66

If I understand correctly, you are trying to preserve the value category of the argument There is two ways to do that:

  • Overloads:
void myFunc(const Object& obj) { handleObject(obj); }
void myFunc(Object&& obj) { handleObject(std::move(obj)); }
  • Forwarding references
template <typename T>
void myFunc(T&& obj) { handleObject(std::forward<T>(obj)); }

In the second case, the && is used for a forwarding reference which preserve the value category of the object. So, if you do not want to duplicate functions, just use forwarding references like the one in your example:

    template <class... Args>
    std::pair<iterator, bool> emplace(Args&&... args) {
       return _insert_unique(std::forward<Args>(args)...);
    }

Hope I did not misunderstand your question

Upvotes: 1

Related Questions