gpt4 book ai didi

c++ - std::vector 的协变包装器

转载 作者:太空狗 更新时间:2023-10-29 21:09:59 30 4
gpt4 key购买 nike

我想要 std::vector 的协变包装器.我的想法是做这样的事情:

  • 创建抽象基类BaseVector<B>谁的beginend方法只是转发给纯虚函数。
  • 创建一个具体的派生类DerivedVector<B, D>包裹着 std::vector<D> .它的beginend方法将隐藏基类的方法,并且它将实现基类转发到的虚拟方法。

这样,如果你有一个指向 BaseVector 的指针你可以迭代基类实例,如果你有一个 DerivedVector您可以迭代派生类实例的指针。

(编辑:显然 BaseVector 不一定支持插入,因为它不知道它包含的对象的类型。也许这意味着“vector ”不是最好的名字为此;我愿意接受建议。谢谢@CygnusX1。)

对于 DerivedVector begin 和 end 方法类可以直接转发到 std::vector的。

问题:我如何实现 BaseVector 的方法? beginend转发?我是否必须编写自己的迭代器类来包装 std::vector迭代器?

或者:是否有更好或更简单的方法来做到这一点?

A DerivedVector<B, D>实例需要通过 BaseVector<B> 可用知道 B 的代码中的指针但不是 D ,并且它需要具有与仅持有派生类 vector 相同的性能(如果调用代码知道派生类)

示例用例:

一个图书馆提供了一个BaseWidget类和一个BaseWidgetPool类,用户从中派生。由于图书馆的性质,在任何给定的程序中都会有一个 DerivedWidget类,但是对于使用该库的每个程序,该类都会有所不同。

BaseWidgetPool类包括迭代池中所有小部件并利用其 BaseWidget 的方法功能。但是每个程序的 DerivedWidgetPool很可能想要使用 DerivedWidget其内容的功能。

(我知道我也可以通过制作一个通用的 WidgetPool<T> 类来处理这个问题,但我宁愿将 T 封装到实际使用它的代码部分。)

最佳答案

有了范围,这就不是问题了。它具有多态范围所需的所有 API:

#include <range/v3/all.hpp>

namespace rv = ranges::view;

int main() {
std::vector<Derived> derived_container;

// ... fill it

ranges::any_view<Base*> base_view =
rv::all(derived_container) | rv::transform([](auto& e) -> Base* { return &e; });

// do stuff with `base_view`
}

那么只要 derived_container 存在,您就可以使用 base_view

我使用了 any_view 这样范围就被类型删除了。您可以在不需要模板化函数的情况下传递它,也可以在虚函数中传递它。

如果您不能使用标准范围或范围 v3,我会创建一个类似的包装器。因此,不是公开类层次结构,而是将其隐藏在实用程序类中。

Live example

当然,any_view 只是为了避免在传递范围类型时模板函数。您可以直接将范围具体化为 vector :

auto base_view =
rv::all(derived_container) | rv::transform([](auto& e) -> Base* { return &e; });

std::vector<Base*> base_container = ranges::to<std::vector>(base_view);

这将避免迭代期间的开销,但需要为新 vector 分配内存。

关于c++ - std::vector 的协变包装器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56342493/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com