Search code examples
c++templatesparameter-passingclass-template

c++ parameter pack specification in constructor rather than template


Unlike function declarations with parameter packs, I've found that classes require the type for each argument in the angle brackets...

Component<IntegerPair, int, int> temp(40, 5);

...which seems redundant. Here's how I defined Component:

template<typename T, class... T_Args>
class Component
{
public:
  Component(T_Args... args)
    : m_data(args...)
  {}

  T m_data;
};
  1. Is there a way to remove int, int from the above statement?
  2. If so, is it ok to remove it?
  3. Also, is my way of instantiation m_data safe? When using std::forward<T_Args>(args)... my compiler told me I didn't have a constructor that could convert all of the argument types.

Solution

  • One way is to make the constructor a template:

    #include <utility>
    
    struct IntegerPair {
        IntegerPair(int, int) {}
    };
    
    template<typename T>
    class Component
    {
    public:
      template<typename... T_Args>
      Component(T_Args&&... args)
        : m_data(std::forward<T_Args>(args)...)
      {}
    
      T m_data;
    };
    
    int main()
    {
        Component<IntegerPair> c {1,2};
    }
    

    This is functionally equivalent to std::vector and its member function emplace_back. It's perfectly ok, IMO. The error messages are pretty cryptic, as usual in template constructs like this, but this can be mitigated with an appropriate static_assert.