1

在 C++11 中是否有可能在不复制任何元素的情况下将许多std::vectors 累积到容器中,每个 s 由给定的函数(我无法更改其 API)返回?std

std::vector<int> make_vect();
container acc;                           // what is container?
do {
    acc.append(std::move(make_vect()));  // how to implement this?
} while(acc.size() < n);

注意 1即使元素没有移动赋值运算符的移动构造函数,也不得复制元素,例如int在示例中。因此,您可以移动一大块元素(通过复制指针),但不能移动单个元素。

注意 2必须container允许使用单个迭代器对所有累积元素进行迭代。所以std::vector<std::vector<>>或类似是不允许的。

显然,编写一些允许这样做的容器或使用std::list<std::vector<>>并提供您自己的迭代器是很简单的,但是std库是否在没有此类用户编写的添加的情况下提供了所需的功能?

看起来所请求的功能并没有什么特别奇怪的,我很惊讶即使使用 C++11 也很难(如果不是不可能的话)。

4

1 回答 1

3

TL;DR我认为库存标准容器不能满足您的要求。这就是为什么。

请记住,容器的移动语义是有效的,因为它们被实现为动态分配内存的范围绑定句柄。移动容器被实现为复制句柄,而不触及包含的元素。

您的第一个(显式)约束是不要复制任何容器的任何元素。这需要将句柄复制到您假定的acc_container. 换句话说,你想要一个acc_container<std::vector<T>>. T无论单个元素有多大,任何标准容器都可以让您有效地做到这一点。

您的第二个(隐式,从评论中推断)约束是您希望在所有单个向量的所有元素上具有统一的接口。换句话说,您想将其用作acc_container<T>. 这需要在你的迭代器中增加一层间接性,迭代acc_container器检测到它已经到达当前一个的末尾vector<T>,然后跳转到下一个的开头vector<T>

标准库中不存在这样的容器。

最简单的解决方法是使用 a std::vector<std::vector<T>>(以避免复制T元素),并编写您自己的迭代器适配器(例如,使用boost::indirect_iterator, 来提供对T元素的迭代)。

不幸的是,即使您提供从成员/初始化这些间接迭代器的非成员begin()/end()函数,range-for 也不会使用 ADL 来查找这些函数,因为它会更喜欢旧的成员函数/ 。此外,您将无法例如将元素直接放入您的复合容器中,除非您还提供非成员(并且类似地提供其他功能)。.begin().end().begin().end()insert()Tinsert()

因此,如果您想要一个真正的复合容器,具有范围支持和成员函数的本机接口,您需要自己编写一个(std::vector<std::vector<T>作为后端,整个std::vector<T>接口都写在它上面)。也许您可以在 Boost 邮件列表中将其作为一个不错的项目来推荐。

更新:这是 Matt Austern 关于分段迭代器和分层算法的旧论文的链接,该论文显示了这种方法的一些性能优势。缺点是您还需要让标准算法了解这些迭代器。

于 2013-09-13T07:24:50.947 回答