【问题标题】:Why can't emplace accept begin and end as parameter为什么不能接受开始和结束作为参数
【发布时间】:2021-08-14 04:19:50
【问题描述】:

我正在为我的团队开发一个基本(低级)c++11 库。现在我正在尝试开发一个自定义容器。

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;
}

std::map::emplace好像不能接受两个参数:开始和结束?

那么为什么std::map::insert 可以接受开始和结束但std::map::emplace 不能呢?

在我的代码的函数void emplace中,我必须使用循环吗?

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

【问题讨论】:

  • 传递给emplace 的参数需要能够构造std::pair&lt;const T1, T2&gt;,因为它们只是直接转发到那里。 insert 特别有一个重载,允许您插入范围的内容,但 emplace 用于就地构造单个元素。
  • 您所询问的功能值得一读。
  • @sweenish 我读过std::map::emplace。但它并没有告诉我为什么它是这样设计的。为什么标准不使用两个迭代器类型的参数重载这个函数?
  • 简单的答案是,这不是函数的设计目的。你想要的并不在 emplace 的意图附近。你说你读过它,但它看起来根本不像。

标签: c++ c++11 stdmap emplace


【解决方案1】:

emplace 将参数传递给序列中包含的元素的构造函数。在这种情况下,它是std::pair&lt;const Key, Value&gt;,因此当您调用emplace 时,您提供的参数将传递给std::pair 的构造函数。由于两个迭代器都不是有效的参数,它不会编译。

这些示例来自 cppreference,让您了解 emplace 的实际使用方式:

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'));

【讨论】:

  • 好的。不过,我不知道为什么标准不会用两个迭代器重载 emplace 函数......既然insert 可以从头到尾插入,为什么我们不能emplace 从头到尾插入。
  • @Yves 假设 emplace 确实采用了一对迭代器,您希望它与 insert 有什么不同的行为?
猜你喜欢
  • 2015-12-15
  • 2011-05-29
  • 1970-01-01
  • 2011-11-02
  • 2015-04-16
  • 2020-06-22
  • 2022-12-19
  • 2022-09-23
相关资源
最近更新 更多