2

I have a constexpr auto my_tuple = std::make_tuple(a, b, c, d, e);. Now, I want to apply a constexpr function over every of its elements. I thought that I could do it like this:

template <typename... Types>
void constexpr apply_func_on_tuple(std::tuple<Types...> tpl) noexcept
{
    for (std::size_t i = 0; i < sizeof...(Types); ++i)
    {
        my_function(std::get<i>(tpl));
    }
}

But it doesn't work. I learned why I can't do it this way after reading this. Is there any other way to accomplish what I want fully at compile-time?

  • I don't know that any answer will get much better than those [in this question](https://stackoverflow.com/questions/28110699/what-does-this-variadic-template-code-do) apart from mentioning C++20's `for...` statement. – chris Jun 29 '19 at 18:31
  • Boost::Hana::for_each works for std::tuple https://www.boost.org/doc/libs/1_61_0/libs/hana/doc/html/fwd_2for__each_8hpp.html you need to include both for_each header and the. boost/Hana/ext/std/tuple.hpp – Hui Jun 29 '19 at 19:41

1 Answers1

3

You can't use a regular for loop, but you can write a constexpr function that works just like a loop:

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

template <auto N, typename F>
constexpr void static_for(F &&func)
{
    static_for_low(func, std::make_integer_sequence<decltype(N), N>{});
}

Then you can do following:

template <typename ...Types>
constexpr void apply_func_on_tuple(std::tuple<Types...> tpl) noexcept
{
    static_for<sizeof...(Types)>([&](auto index)
    {
        my_function(std::get<index.value>(tpl));
    });
}
HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207