Ashley Ben Story
Ashley Ben Story

Reputation: 47

How do I pass a parameter pack to a std:tuple?

This is a simple question, yet the Internet offers no answer or examples to this one: what is the correct means of passing a parameter pack to a std::tuple ?

I have tried the following, only to find I received the error:

'missing template arguments before token':

#include <tuple>
#include <iostream>

template <typename... Args>
std::tuple <Args...> footup;

template <typename... Args>
void bar(std::tuple <Args...>& footup, Args... args)
{
    footup = std::make_tuple(args...);
}

int main()
{
    bar(footup, 1, 2, 3, 4, 5, 6, 7);
    std::cout << std::get <0>(footup) << " "
        << std::get <1>(footup) << " "
        << std::get <2>(footup) << "\n\n";

    return 0;
}

How do I prevent the error message and have the parameter pack work?

Upvotes: 1

Views: 139

Answers (3)

JeJo
JeJo

Reputation: 33092

How do I prevent the error message and have the parameter pack work?

You should not be passing the variable template footup directly to the function. You need an instantiated instance of that variable template here. That means,

// Variable template
template <typename... Args> std::tuple <Args...> footup;

 // Create a reference to the instantiated variable template "footup" for bar()
auto& footupInstance = footup<int, int, int, int>;

Now, the easiest would be, adding extra template parameter for footupInstance.

template <typename Tuple, typename... Args>
//       ^^^^^^^^^^^^^^^^
void bar(Tuple& footupInstance , Args&&... args)
{
    footupInstance = std::make_tuple(std::forward<Args>(args)...);
}

See demo


Or do not use the helper bar, and use the std::make_tuple directly in the main() to create the tuple with desired Args...:

#include <tuple>

int main()
{
    /* const */ auto footupInstance = std::make_tuple(1, 2, 3, 4, 5, 6, 7);

    // The type of footupInstance (if required).
    using MyTupleT = decltype(footupInstance);
}

Upvotes: 3

Ted Lyngmo
Ted Lyngmo

Reputation: 118097

footup is a variable template and not an instance variable. You can't pass it around as-if it was an instance.

You could instantiate a variable with it and use that in the call to bar:

#include <iostream>
#include <tuple>

template <typename... Args>
std::tuple<Args...> footup;

template <class... Args>
void bar(std::tuple<Args...>& instance, Args&&... args) {
    instance = std::make_tuple(std::forward<Args>(args)...);
}

int main() {
    auto& instance = footup<int, int, int, int, int, int, int>;
    // or if you'd like a copy:
    // auto instance = footup<int, int, int, int, int, int, int>;

    bar(instance, 1, 2, 3, 4, 5, 6, 7);
    std::cout << std::get<0>(instance) << ' ' << std::get<1>(instance) << ' '
              << std::get<2>(instance) << '\n';
}

Upvotes: 4

William Chan
William Chan

Reputation: 43

I guess what you want is to construct a tuple from a parameter block:

#include <tuple>
#include <iostream>
#include <utility>

template <typename... Args>
std::tuple<Args...> bar(Args&&... args)
{
    return std::make_tuple(std::forward<Args>(args)...);
}

int main()
{
    auto footup = bar(1, 2, 3, 4);
    std::cout << std::get<0>(footup) << " "
        << std::get<1>(footup) << " "
        << std::get<2>(footup) << " "
        << std::get<3>(footup) << "\n";

    return 0;
}

online demo

Upvotes: 0

Related Questions