前/后插入器In_place

时间:2018-01-16 02:35:45

标签: c++ iterator c++14

在我学习的过程中,我遇到了前后迭代器,我想知道是否有办法让他们在适当的位置创建容器元素。从文档中可以看出,容器需要实现与back_iterator一起使用的push_back函数。但有没有办法在元素创造上占有一席之地?

1 个答案:

答案 0 :(得分:2)

您所询问的内容在概念上是不可能的。

作为概念的迭代器表示某个对象的抽象,该对象在该类型的一系列元素中引用某种类型的元素。因此,basic Iterator concept具有取消引用迭代器的能力作为核心特征。那就是*it是一个合法的表达式(尽管基本的迭代器没有说明它的返回值是什么)。

back_insert_iterator通过......实现*it来实现它。 OutputIterator concept允许*it,但其结果未指定,因此您无法直接使用它。相反,你应该在像*it++ = value;这样的表达式中使用它。 operator=重载是实际调用push_back

这模仿了像指针这样的自然迭代器的行为。它允许OutputIterator 假装以允许您在实际使用operator=来呼叫container.push_back时分配给现有值。 *++只是匹配ForwardIterators的界面。

但是operator=是一个运营商。它是一个函数,只需要两个参数:迭代器(左侧)和赋值给它的值。

emplace - 类似的函数通过调用具有任意参数序列的构造函数来工作。通过operator=无法做到这一点。由于OutputIterator的接口仅限于此,因此迭代器没有有效的方法来使用这样的就地构造。

请注意,技术上有一种方法可以做到这一点。您需要的是一种在单个值中打包多个值的方法:

auto it = back_emplacer(...);
*it++ = std::forward_as_tuple(...);

operator=看起来像这样:

template<typename ...Args>
back_emplace_iterator &operator=(std::tuple<Args...> &&args)
{
  std::apply(
    [container](auto ...&&args)
      {container->emplace_back(std::forward<decltype(args)>(args)...);},
    std::forward<std::tuple<Args>>(args));
  return *this;
}

当然,缺点是您必须在转发tuple中手动打包数据。