user12130309
user12130309

Reputation:

How to unpack tuple with unknown size?

Given,

template<typename T>
void foo(T t)
{
    std::tie(/*xxx*/)=t;
    auto &[/*yyy*/]=t;
}
int main()
{
    foo(forward_as_tuple(1,2,3));
    foo(forward_as_tuple(1,2,3,4,5));
}

I want foo() to unpack the tuple that's passed to itself. Can decomposition declarations with auto or std::tie(), handle the unknown tuple sizes like xxx - yyy up there?
If yes, how?

I'm trying to think of another ways, maybe all elements could be pushed back to a vector of that type, once they're got.

std::vector<T> bar;
size_t baz=std::tuple_size<T>::value; //useless because it can't be used as:
for(int i=0; i<baz; i++)
    bar.push_back(std::get<i>(t)); //since i isn't constant

Using vectors was just a bad idea that failed.
How else can it be done?

What I'm trying to, shortly is; I want to get tuple elements in a for loop. That's why I think I need them to be extracted somehow.

Upvotes: 0

Views: 880

Answers (2)

eerorika
eerorika

Reputation: 238451

How to unpack tuple with unknown size?

auto &[/*yyy*/]=t;

You can't.

maybe all elements could be pushed back to a vector of that type

Use std::apply:

std::vector<int> baz;
std::apply([&baz](auto... args) {
    (baz.push_back(args), ...);
}, t);

Upvotes: 3

HolyBlackCat
HolyBlackCat

Reputation: 96886

What I'm trying to, shortly is; I want to get tuple elements in a for loop.

You don't need to unpack a tuple to iterate over it. Here's how I'd do it:

template <typename Integer, Integer ...I, typename F>
constexpr void constexpr_for_each(std::integer_sequence<Integer, I...>, F &&func)
{
    (func(std::integral_constant<Integer, I>{}) , ...);
}

template <auto N, typename F>
constexpr void constexpr_for(F &&func)
{
    if constexpr (N > 0)
    {
        constexpr_for_each(std::make_integer_sequence<decltype(N), N>{}, std::forward<F>(func));
    }
}

template <typename T>
void foo(T t)
{
    constexpr_for<std::tuple_size_v<T>>([&](auto index)
    {
        constexpr auto i = index.value;

        std::cout << std::get<i>(t) << '\n';
    });
}

Upvotes: 3

Related Questions