4

I have a class that is declared with this template: template <typename ...Args>. In it, I have a list declared as std::vector<std::tuple<Args...>> vec; to store data entries specified by the template. I also have a function declared as follows:

void AddVertex(Args... data)
{
    // vec.push_back(std::tuple<Args...>(data));
}

In this function, I want to add a tuple of Args... to the vector. Is this possible? I have tried using the code in the comment, but the compiler gives me an error saying that "the parameter pack must be expanded in this context".

This solution doesn't work, because the template argument of the tuple is already expanded.

Lázár Zsolt
  • 685
  • 8
  • 29
  • Include the real vector in your function. Obviously it isn't a member variable somewhere. A [mcve] with everything but the push would do nicely. – WhozCraig Dec 14 '19 at 19:35

2 Answers2

5

You need to expand both:

  • template parameters pack (Args...)

and

  • function parameters pack (data...):

so it should be:

    vec.push_back(std::tuple<Args...>(data...));

Or shorter form, use make_tuple:

    vec.push_back(std::make_tuple(data...));
rafix07
  • 20,001
  • 3
  • 20
  • 33
3

As hinted by the compiler, you need to expand the parameter pack data, so this should work:

void AddVertex(Args... data)
{
    vec.push_back(std::tuple<Args...>(args...));
}

Also, consider using emplace_back instead:

void AddVertex(Args... data)
{
    vec.emplace_back(args...);
}

Both of the above functions will copy every argument and thus are not idiomatic C++. This may or may not be an issue to you. To avoid this do something like

template <typename... T>
void AddVertex(T&&... args)
{
    vec.emplace_back(std::forward<T>(args)...);
}

which is a little more verbose, but will avoid those unnecessary copies.

elbrunovsky
  • 442
  • 5
  • 11