【问题标题】:How to make a pointer vector by a list of sub types?如何通过子类型列表制作指针向量?
【发布时间】:2014-05-17 05:03: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;
}

我尝试了上面的代码,但失败了。我不清楚参数包的扩展。有什么方法可以纠正它或者它只是一个编译器错误?

【问题讨论】:

  • 我想你可以对in other way感兴趣,它可以在需要初始化不可复制对象的vector时使用(没有emplace_back)。

标签: c++ templates variadic-templates


【解决方案1】:

您只能在某些情况下进行参数包扩展。完整的语句级别不是其中之一。

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 的右大括号结束后才会扩展。

【讨论】:

  • 我试试empty unused[]= { (void( std::forward&lt;Fs&gt;(fs) ), empty{})... };。这也很好。结尾empty()是必须的吗?
  • 嗯,我得到了一个silly little helper,它使它工作......不过,与你的代码没有足够的不同。
  • @user1899021 Ts 的空集是非法的。 , empty{} 使其合法。
猜你喜欢
  • 2018-02-26
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 2019-07-20
  • 1970-01-01
  • 1970-01-01
  • 2019-08-28
相关资源
最近更新 更多