Alternative to integer_sequence trick I hate working with std::integer_sequence. Each time I want to write a function foo I have to write an another function foo_impl where the actual stuff is happening. Therefore I'm polluting the space with additional function and the code is kind of scattered around. I came up with an alternative and I would love to know your opinion. 



Let's define integral_sequence&lt;N&gt;. Here we use the damned std::integer_sequence for the last time!

template &lt;std::size_t... I&gt;
constexpr auto integral_sequence_impl(std::index_sequence&lt;I...&gt;) {
  return std::make_tuple(std::integral_constant&lt;std::size_t, I&gt;{}...);
}

template &lt;int N&gt;
auto integral_sequence = integral_sequence_impl(std::make_index_sequence&lt;N&gt;{});


To demonstrate its use, lets redo the example code for std::integral_sequence:

// Convert array into a tuple
template &lt;typename T, std::size_t N&gt;
decltype(auto) a2t(const std::array&lt;T, N&gt; &amp;a) {
  auto impl = [&amp;](auto... I) { return std::make_tuple(a[I]...); };

  return std::apply(impl, integral_sequence&lt;N&gt;);
}

// pretty-print a tuple
template &lt;class Ch, class Tr, class... Args&gt;
decltype(auto) operator&lt;&lt;(std::basic_ostream&lt;Ch, Tr&gt; &amp;os,
                          const std::tuple&lt;Args...&gt; &amp; t) {

  auto impl = [&amp;](auto... I) {
    ((os &lt;&lt; (I == 0 ? "" : ", ") &lt;&lt; std::get&lt;I&gt;(t)), ...);
  };

  os &lt;&lt; "(";
  std::apply(impl, integral_sequence&lt;sizeof...(Args)&gt;);
  return os &lt;&lt; ")";
}

int main() {
  std::array&lt;int, 4&gt; array = {1, 2, 3, 4};

  // convert an array into a tuple
  auto tuple = a2t(array);
  static_assert(
      std::is_same&lt;decltype(tuple), std::tuple&lt;int, int, int, int&gt;&gt;::value, "");

  // print it to cout
  std::cout &lt;&lt; tuple &lt;&lt; '\n';
}


The trick with integral_sequence is kind of the same as with integer_sequence. However, because it can be used with generic lambda you do not have to define an extra function, all code can be neatly together and it reduces visual clutter.

So what do you think? Are there any disadvantages?

The only problems I can see now is that it is only c++17 and integral_sequence&lt;400&gt; takes really long time to compile.
Looks good to me! I mean, I'm not likely to convert to it because of its heavyweightness — you noted its use of std::apply, but it also pulls in all of &lt;tuple&gt; every time you use it, too. Also, it's arguably coincidental that your expressions a[I] and std::get&lt;I&gt;(t) work in this context, since what's actually happening in both cases is an implicit conversion from std::integral_constant&lt;size_t, K&gt; to size_t. In some contexts, the user might need to explicitly cast int(I) or whatever.

You could remove the std::apply dependency and simplify the user's job at the same time by writing a helper function apply_to_sequence&lt;N&gt;(lambda), as in:

// Convert array into a tuple
template &lt;typename T, std::size_t N&gt;
auto a2t(const std::array&lt;T, N&gt;&amp; a) {
  return apply_to_sequence&lt;N&gt;([&amp;](auto... Is) {
      return std::make_tuple(a[Is]...);
  });
}


(Oh yeah, I think your use of decltype(auto) in this function was bogus and could result in dangling references. Certainly auto would be fine, so I recommend it.)

// pretty-print a tuple
template &lt;class Ch, class Tr, class... Args&gt;
auto&amp; operator&lt;&lt;(std::basic_ostream&lt;Ch, Tr&gt;&amp; os,
                          const std::tuple&lt;Args...&gt;&amp; t)
{
  os &lt;&lt; "(";
  apply_to_sequence&lt;sizeof...(Args)&gt;([&amp;](auto... Is) {
    ((os &lt;&lt; (Is == 0 ? "" : ", ") &lt;&lt; std::get&lt;Is&gt;(t)), ...);
  });
  return os &lt;&lt; ")";
}


Writing apply_to_sequence from scratch is left as an exercise for the reader, but the trivial C++17 implementation is just this:

template&lt;size_t N, class F&gt;
decltype(auto) apply_to_sequence(const F&amp; fn) {
    return std::apply(fn, integral_sequence&lt;N&gt;);
}


Having hidden the implementation details apply and integral_sequence from the reader, we are now free — if we so desire — to replace them with things that are


faster
C++14-compatible
&lt;tuple&gt;-free


One stylistic note: I prefer to name my parameter packs with plurals, so, singular auto I but plural auto... Is. That's the logic behind my renaming above.