Search code examples
c++templatesconstructorvariadic-templatessmart-pointers

Create object using parameters pack in template


I'd like to create template function that would create object basing on template typename and parameters pack.

I created a function that is supposed to create object based on typename from template, and I would also like to pass parameters pack to that template i order to pass parameters to constructor. Is this correct?:

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

I also wanted to pass those parameters to another fucntion like this:

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

But compiler returns an error " 'args' parameter pack must be expanded in this context"

Is it even possible to achieve what I want to achieve ?


Solution

  • But compiler returns an error " 'args' parameter pack must be expanded in this context"

    Yes: you've forgotten to expand the types

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

    As pointed by Jarod42, according to the circumstances, you could avoid to explicit the Args... expansion

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

    and let the compiler deduce the types through args... (but we should see the AddComponent() definition).

    Anyway, I don't see errors in your CreateComponents() function but, as correctly says François Andrieux in a comment, you don't using perfect forwarding.

    It's a too-great argument to explain in an answer but, this way, you're renouncing to move semantics advantages (that is: you, potentially, make some unnecessary copies).

    The following is your CreateComponents() function enabling perfect forwarding

    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)...);
     } // ..............................^^^^^^^^^^^^^^^^^^^^^^^^