[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