Lázár Zsolt
Lázár Zsolt

Reputation: 833

How do I create an std::tuple<> from a variadic template parameter?

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.

Upvotes: 4

Views: 2728

Answers (2)

elbrunovsky
elbrunovsky

Reputation: 440

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.

Upvotes: 3

rafix07
rafix07

Reputation: 20918

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...));

Upvotes: 5

Related Questions