使用模板中的参数包创建对象

时间:2019-05-22 19:36:26

标签: c++ templates constructor variadic-templates smart-pointers

我想创建模板函数,该函数将基于模板类型名和参数包创建对象。

我创建了一个函数,该函数应该根据模板的类型名创建对象,并且我还想将参数包传递给该模板,以便将参数传递给构造函数。这是正确的吗?:

template<typename TComponent, typename... Args>
    void CreateComponent(Args... args) 
    {
        std::shared_ptr<TComponent> component = std::make_shared<TComponent>(args ...);
    }

我还想将这些参数传递给另一个函数,例如:

template<typename TComponent, typename... Args>
    void AddComponent(Args... args) 
    {
          m_world->AddComponent<TComponent, Args>(m_id, args...);
    }

但是编译器返回错误“在这种情况下必须扩展'args'参数包”

是否有可能实现我想要实现的目标?

1 个答案:

答案 0 :(得分:3)

  

但是编译器返回错误“在这种情况下必须扩展'args'参数包”

是:您忘记扩展类型了

m_world->AddComponent<TComponent, Args...>(m_id, args...);
// ...................................^^^

正如Jarod42所指出的,根据情况,您可以避免显式Args...扩展

m_world->AddComponent<TComponent>(m_id, args...);
// no more Args...

,然后让编译器通过args...推断类型(但我们应该看到AddComponent()的定义)。

无论如何,我看不到您的CreateComponents()函数中的错误,但是正如FrançoisAndrieux在评论中正确说的那样,您没有使用完美的转发。

在回答中解释这是一个太过分的论点,但是,这样,您就放弃了语义优势的转移(即:您可能会制作一些不必要的副本)。

以下是您的CreateComponents()功能,可实现完美转发

template <typename TComponent, typename ... Args>
void CreateComponent (Args && ... args) 
 { // .....................^^ forwarding reference added
   std::shared_ptr<TComponent> component
     = std::make_shared<TComponent>(std::forward<Args>(args)...);
 } // ..............................^^^^^^^^^^^^^^^^^^^^^^^^