在学习过程中,我遇到了前迭代器和后迭代器,我想知道是否有办法让它们就地创建容器元素。从文档来看,容器似乎需要实现push_back函数才能与back_iterator一起使用。但是有没有一种方法可以实现元素创建呢?
最佳答案
您所问的问题在概念上是不可能的。
迭代器作为一个概念表示某个对象的抽象,该对象引用一系列该类型的元素中的某种类型的元素。因此,basic Iterator
concept具有取消引用迭代器的能力作为核心功能。也就是说 *it
是一个合法的表达式(虽然基本的 Iterator 并没有说明它的返回值是什么)。
back_insert_iterator
通过...不实现它来实现*it
。 OutputIterator concept允许*it
,但它的结果是未指定的,所以你不能真正直接使用它。相反,您应该在像 *it++ = value;
这样的表达式中使用它。实际上调用 push_back
的是 operator=
重载。
这模仿了指针等自然迭代器的行为。它允许 OutputIterator 假装允许您分配给现有值,而您实际上是使用 operator=
调用 container.push_back
。 *
和 ++
只是为了匹配 ForwardIterators 的接口(interface)。
但是 operator=
是一个运算符。它是一个只接受两个参数的函数:迭代器(左侧)和分配给它的值。
emplace
类函数通过使用任意参数序列调用构造函数来工作。无法通过 operator=
来做到这一点。由于 OutputIterator 的接口(interface)仅限于此,因此迭代器没有有效的方法来使用这样的就地构造。
请注意,技术上有一种方法可以做到这一点。您需要的是一种将多个值打包到一个值中的方法:
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;
}
当然,缺点是您必须手动将数据打包到转发元组
中。
关于c++ - 前/后插入器就位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48273319/