[libcxx-commits] [libcxx] [libc++][utility] Add fallback implementation for __make_integer_sequence_impl (PR #192789)

via libcxx-commits libcxx-commits at lists.llvm.org
Sat Apr 18 06:42:01 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Kim-J-Smith

<details>
<summary>Changes</summary>

[libc++][utility] Add fallback implementation for __make_integer_sequence_impl

When neither __make_integer_seq nor __integer_pack is available, provide a pure C++11 metaprogramming fallback using divide-and-conquer.

The implementation splits the target size into quotient (N/8) and remainder (N%8), recursively builds base sequences, then merges them with appropriate offsets. For small sizes (<8) it expands linearly.

This allows std::integer_sequence (and make_integer_sequence) to work on compilers that lack these builtins, e.g., older GCC or custom toolchains without __make_integer_seq / __integer_pack.

---
Full diff: https://github.com/llvm/llvm-project/pull/192789.diff


1 Files Affected:

- (modified) libcxx/include/__utility/integer_sequence.h (+43-1) 


``````````diff
diff --git a/libcxx/include/__utility/integer_sequence.h b/libcxx/include/__utility/integer_sequence.h
index a84f572c3339c..de32cca09c5cd 100644
--- a/libcxx/include/__utility/integer_sequence.h
+++ b/libcxx/include/__utility/integer_sequence.h
@@ -26,9 +26,51 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 #  if __has_builtin(__make_integer_seq)
 template <template <class _Tp, _Tp...> class _BaseType, class _Tp, _Tp _SequenceSize>
 using __make_integer_sequence_impl _LIBCPP_NODEBUG = __make_integer_seq<_BaseType, _Tp, _SequenceSize>;
-#  else
+#  elif __has_builtin(__integer_pack)
 template <template <class _Tp, _Tp...> class _BaseType, class _Tp, _Tp _SequenceSize>
 using __make_integer_sequence_impl _LIBCPP_NODEBUG = _BaseType<_Tp, __integer_pack(_SequenceSize)...>;
+#  else
+// No known way to get an integer pack from the compiler.
+namespace detail {
+
+template <template <class _Tp, _Tp...> class _Base, class _Qu, class _Re>
+struct __merge_seq;
+template <template <class _Tp, _Tp...> class _Base, class _Tp, _Tp... _Qs, _Tp... _Rs>
+struct __merge_seq<_Base, _Base<_Tp, _Qs...>, _Base<_Tp, _Rs...>> {
+  static constexpr std::size_t QuotientSize = sizeof...(_Qs);
+  using type = _Base<
+      _Tp, 
+      0 * QuotientSize + _Qs..., 1 * QuotientSize + _Qs..., 2 * QuotientSize + _Qs...,
+      3 * QuotientSize + _Qs..., 4 * QuotientSize + _Qs..., 5 * QuotientSize + _Qs...,
+      6 * QuotientSize + _Qs..., 7 * QuotientSize + _Qs..., 8 * QuotientSize + _Rs...>;
+};
+
+template <template <class _Tp, _Tp...> class _Base, class _Tp, size_t _Tgt, size_t _Cnt, _Tp... _Nx>
+struct __make_small_seq {
+  using type = typename __make_small_seq<_Base, _Tp, _Tgt, _Cnt + 1, _Nx..., _Cnt>::type;
+};
+template <template <class _Tp, _Tp...> class _Base, class _Tp, size_t _Tgt, _Tp... _Nx>
+struct __make_small_seq<_Base, _Tp, _Tgt, _Tgt, _Nx...> {
+  using type = _Base<_Tp, _Nx...>;
+};
+
+template <template <class _Tp, _Tp...> class _Base, class _Tp, size_t _Tgt, class _Seq, bool _IsSmall = (_Tgt < 8)>
+struct __make_integer_seq_impl {
+  using type = typename __merge_seq<
+      _Base,
+      typename __make_integer_seq_impl<_Base, _Tp, _Tgt / 8, _Seq>::type,
+      typename __make_integer_seq_impl<_Base, _Tp, _Tgt % 8, _Seq>::type
+    >::type;
+};
+template <template <class _Tp, _Tp...> class _Base, class _Tp, size_t _Tgt, class _Seq>
+struct __make_integer_seq_impl<_Base, _Tp, _Tgt, _Seq, true> {
+  using type = typename __make_small_seq<_Base, _Tp, _Tgt, 0>::type;
+};
+
+} // namespace detail
+template <template <class _Tp, _Tp...> class _BaseType, class _Tp, _Tp _SequenceSize>
+using __make_integer_sequence_impl _LIBCPP_NODEBUG = 
+    typename detail::__make_integer_seq_impl<_BaseType, _Tp, _SequenceSize, _BaseType<_Tp>>::type;
 #  endif
 
 template <class _Tp, _Tp... _Indices>

``````````

</details>


https://github.com/llvm/llvm-project/pull/192789


More information about the libcxx-commits mailing list