如何从模板方法内的参数包中移动 unique_ptr

The*_*moo 0 c++ templates unique-ptr

我想将一个参数包传递到一个模板方法中,该方法创建一个由另一个模板参数指定的类型的对象的新实例。

最小代码示例

我的代码实际上使用创建的类型和处理程序执行更多操作

template<typename T, typename... Args>
static bool CreateAndDo(Handler & rHandler, Args.. args)
{
  auto pT = T::Create(args...);
  rHandler.DoStuff(std::move(pT));
}
Run Code Online (Sandbox Code Playgroud)

简单用法:

Handler tHander;
// the 0 is just an example of an argument
CreateAndDo<ConcreteType>(tHander, 0);
Run Code Online (Sandbox Code Playgroud)

现在我的问题是我的一个论点是std::unique_ptr.

auto pPtr = std::make_unique<ConcreteArg>();
CreateAndDo<ConcreteType>(tHander, std::move(pPtr));
Run Code Online (Sandbox Code Playgroud)

这将无法编译,因为std::unique_ptr必须由CreateAndDoMethod移动。我知道我需要不断移动参数,但我不知道如何使用参数包来做到这一点。

我怎么能做到这一点?

Lig*_*ica 5

嗯,你为什么移动args...

你总是在复制,在 CreateAndDo 中。正如您所发现的,没有理由,并且它禁止您传递仅移动参数。

我看不出这与模板或参数包有什么关系,真的,除非问题是不清楚如何在这种情况下完成移动。问题不在于如何将 a 传递unique_ptr给参数包,而是之后如何处理它,这与没有参数包的情况相同 - 移动 a unique_ptr

您应该转发args,它会在适当的时候有效地进行移动,否则会进行复制。您还需要将参数作为转发引用

template<typename T, typename... Args>
static bool CreateAndDo(Handler & rHandler, Args&&.. args)
{
  auto pT = T::Create(std::forward<Args>(args)...);
  rHandler.DoStuff(std::move(pT));
}
Run Code Online (Sandbox Code Playgroud)

所以问题是你只移动了函数调用链的一部分,而不是第二部分,导致不必要的——有时是不可能的——复制。