0

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.
  • 1
    You're basically asking if it's possible to deduce class template arguments from a constructor call - to which the asnwer is *no*. What you'll need is a "maker" function - like for example `std::make_pair` is, or a constructor template. – jrok Jul 19 '15 at 07:13
  • 3: you need to take in a universal reference `T_Args&&` to use perfect forwarding – tkausl Jul 19 '15 at 07:14
  • Relevant: http://stackoverflow.com/questions/29677505/why-cant-constructors-deduce-template-arguments – cpplearner Jul 19 '15 at 07:17

2 Answers2

3

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.

jrok
  • 54,456
  • 9
  • 109
  • 141
  • That's exactly what I was looking for, and you also fixed the forwarding. Why the curly braces for the arguments? – user3097902 Jul 19 '15 at 07:30
  • 1
    @user3097902 For no particular reason, it's newer syntax :) Parentheses would br equivalent in this case. – jrok Jul 19 '15 at 07:48
0

template parameter deduction only work for function calls so the basic pattern to achieve what you want looks like this:

template<typename T, class... T_Args>
Component<T, T_Args...> makeComponent(T_Args&&... args) {
   return Component<T, T_Args...>(std::forward<T_Args>(args)...);
}

Usage:

auto c = makeComponent<IntegerPair>(1, 1)
shoosh
  • 76,898
  • 55
  • 205
  • 325