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