如何通过子类型列表创建指针向量

How to make a pointer vector by a list of sub types?

本文关键字:创建 指针 向量 列表 类型 何通过      更新时间:2023-10-16

我有一个基类型B和它的子类型列表,比如B1, B2,它们都是从B派生出来的。我想开发一个函数来创建一个指针向量,它的元素是新的B1,新的B2,等等,比如

template<class BaseType, class... SubTypes>
vector<unique_ptr<BaseType>> makePtrVector()
{
     vector<unique_ptr<BaseType>> v;
     v.emplace_back(new SubTypes)...; // error, SubTypes has to be expanded
     return v;
}
我尝试了上面的代码,但失败了。我不清楚参数包的扩展。有什么方法来纠正它或它只是一个编译器的错误?

只能在特定上下文中进行参数包展开。完整语句级别不在其中。

std::vector::emplace_back返回void,所以我们可以这样做:

struct empty {};
template<class BaseType, class... SubTypes>
vector<unique_ptr<BaseType>> makePtrVector() {
  vector<unique_ptr<BaseType>> v;
  empty unused[]= {(v.emplace_back(new SubTypes), empty{})..., empty{}}; // error
  return v;
}

,其中我们创建了empty类型的初始化列表,作为其构造的副作用,调用您喜欢的代码。(int也很流行)。

另一种方法是将其移动到辅助函数中。然而,这并不适用于每个编译器:

template<typename...Fs>
void do_in_order( Fs&&... fs ) {
  empty unused[]= { (void( std::forward<Fs>(fs) ), empty{})..., empty{} };
}

然后在你的代码中:

template<class BaseType, class... SubTypes>
vector<unique_ptr<BaseType>> makePtrVector() {
  vector<unique_ptr<BaseType>> v;
  do_in_order( [&]{ v.emplace_back(new SubTypes); }... );
  return v;
}

哪个看起来不那么钝,不是吗?缺点是一些主要的编译器不喜欢lambda中不完整的参数包,这些参数包只在lambda的右括号结束后展开。