Search code examples
c++c++11stdmapemplace

Why can't emplace accept begin and end as parameter


I'm developing a basic(low-level) c++11 library for my team. Now I'm trying to develop a custom container.

template<typename T1, typename T2>
class CustomMap {
public:
    void insert(const std::map<T1, T2>& container) { mp_.insert(container.begin(), container.end()); }
    void emplace(std::map<T1, T2>&& container) { mp_.emplace(container.begin(), container.end()); }

private:
    std::map<T1, T2> mp_;
};

int main() {
    CustomMap<int, int> mp;
    std::map<int, int> mm;
    mm[1] = 2;
    mp.emplace(std::move(mm)); // ERROR

    return 0;
}

It doesn't seem that std::map::emplace can accept two parameters: begin and end?

So why can std::map::insert accept begin and end but std::map::emplace can't?

In the function void emplace of my code, I have to use a loop?

for (auto && ele : container) {
    mp_.emplace(ele);
}

Solution

  • emplace takes arguments to pass to the constructor of the contained elements of the sequence. In this case, it's a std::pair<const Key, Value>, so when you call emplace the arguments you provide are passed to the constructor of a std::pair. As two iterators are not valid arguments, it won't compile.

    These examples are from cppreference, to give you ideas of how emplace is actually used:

    std::map<std::string, std::string> m;
    
    // uses pair's move constructor
    m.emplace(std::make_pair(std::string("a"), std::string("a")));
    
    // uses pair's converting move constructor
    m.emplace(std::make_pair("b", "abcd"));
    
    // uses pair's template constructor
    m.emplace("d", "ddd");
    
    // uses pair's piecewise constructor
    m.emplace(std::piecewise_construct,
              std::forward_as_tuple("c"),
              std::forward_as_tuple(10, 'c'));