xref: /freebsd-src/contrib/llvm-project/libcxx/include/__utility/integer_sequence.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
2fe6060f1SDimitry Andric //
3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric 
9fe6060f1SDimitry Andric #ifndef _LIBCPP___UTILITY_INTEGER_SEQUENCE_H
10fe6060f1SDimitry Andric #define _LIBCPP___UTILITY_INTEGER_SEQUENCE_H
11fe6060f1SDimitry Andric 
12fe6060f1SDimitry Andric #include <__config>
13bdd1243dSDimitry Andric #include <__type_traits/is_integral.h>
14bdd1243dSDimitry Andric #include <cstddef>
15fe6060f1SDimitry Andric 
16fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
17fe6060f1SDimitry Andric #  pragma GCC system_header
18fe6060f1SDimitry Andric #endif
19fe6060f1SDimitry Andric 
20fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
21fe6060f1SDimitry Andric 
22cb14a3feSDimitry Andric template <size_t...>
23cb14a3feSDimitry Andric struct __tuple_indices;
24bdd1243dSDimitry Andric 
25bdd1243dSDimitry Andric template <class _IdxType, _IdxType... _Values>
26bdd1243dSDimitry Andric struct __integer_sequence {
27bdd1243dSDimitry Andric   template <template <class _OIdxType, _OIdxType...> class _ToIndexSeq, class _ToIndexType>
28bdd1243dSDimitry Andric   using __convert = _ToIndexSeq<_ToIndexType, _Values...>;
29bdd1243dSDimitry Andric 
30bdd1243dSDimitry Andric   template <size_t _Sp>
31bdd1243dSDimitry Andric   using __to_tuple_indices = __tuple_indices<(_Values + _Sp)...>;
32bdd1243dSDimitry Andric };
33bdd1243dSDimitry Andric 
34bdd1243dSDimitry Andric #if __has_builtin(__make_integer_seq)
35bdd1243dSDimitry Andric template <size_t _Ep, size_t _Sp>
36bdd1243dSDimitry Andric using __make_indices_imp =
37cb14a3feSDimitry Andric     typename __make_integer_seq<__integer_sequence, size_t, _Ep - _Sp>::template __to_tuple_indices<_Sp>;
38*0fca6ea1SDimitry Andric #elif __has_builtin(__integer_pack)
39bdd1243dSDimitry Andric template <size_t _Ep, size_t _Sp>
40*0fca6ea1SDimitry Andric using __make_indices_imp =
41*0fca6ea1SDimitry Andric     typename __integer_sequence<size_t, __integer_pack(_Ep - _Sp)...>::template __to_tuple_indices<_Sp>;
42*0fca6ea1SDimitry Andric #else
43*0fca6ea1SDimitry Andric #  error "No known way to get an integer pack from the compiler"
44bdd1243dSDimitry Andric #endif
45bdd1243dSDimitry Andric 
4606c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 14
47fe6060f1SDimitry Andric 
48fe6060f1SDimitry Andric template <class _Tp, _Tp... _Ip>
49cb14a3feSDimitry Andric struct _LIBCPP_TEMPLATE_VIS integer_sequence {
50fe6060f1SDimitry Andric   typedef _Tp value_type;
51cb14a3feSDimitry Andric   static_assert(is_integral<_Tp>::value, "std::integer_sequence can only be instantiated with an integral type");
52cb14a3feSDimitry Andric   static _LIBCPP_HIDE_FROM_ABI constexpr size_t size() noexcept { return sizeof...(_Ip); }
53fe6060f1SDimitry Andric };
54fe6060f1SDimitry Andric 
55fe6060f1SDimitry Andric template <size_t... _Ip>
56fe6060f1SDimitry Andric using index_sequence = integer_sequence<size_t, _Ip...>;
57fe6060f1SDimitry Andric 
58*0fca6ea1SDimitry Andric #  if __has_builtin(__make_integer_seq)
59fe6060f1SDimitry Andric 
60fe6060f1SDimitry Andric template <class _Tp, _Tp _Ep>
61*0fca6ea1SDimitry Andric using make_integer_sequence _LIBCPP_NODEBUG = __make_integer_seq<integer_sequence, _Tp, _Ep>;
62*0fca6ea1SDimitry Andric 
63*0fca6ea1SDimitry Andric #  elif __has_builtin(__integer_pack)
64*0fca6ea1SDimitry Andric 
65*0fca6ea1SDimitry Andric template <class _Tp, _Tp _SequenceSize>
66*0fca6ea1SDimitry Andric using make_integer_sequence _LIBCPP_NODEBUG = integer_sequence<_Tp, __integer_pack(_SequenceSize)...>;
67fe6060f1SDimitry Andric 
68fe6060f1SDimitry Andric #  else
69*0fca6ea1SDimitry Andric #    error "No known way to get an integer pack from the compiler"
70fe6060f1SDimitry Andric #  endif
71fe6060f1SDimitry Andric 
72fe6060f1SDimitry Andric template <size_t _Np>
73fe6060f1SDimitry Andric using make_index_sequence = make_integer_sequence<size_t, _Np>;
74fe6060f1SDimitry Andric 
75fe6060f1SDimitry Andric template <class... _Tp>
76fe6060f1SDimitry Andric using index_sequence_for = make_index_sequence<sizeof...(_Tp)>;
77fe6060f1SDimitry Andric 
7806c3fb27SDimitry Andric #  if _LIBCPP_STD_VER >= 20
79bdd1243dSDimitry Andric // Executes __func for every element in an index_sequence.
80bdd1243dSDimitry Andric template <size_t... _Index, class _Function>
81bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __for_each_index_sequence(index_sequence<_Index...>, _Function __func) {
82bdd1243dSDimitry Andric   (__func.template operator()<_Index>(), ...);
83bdd1243dSDimitry Andric }
8406c3fb27SDimitry Andric #  endif // _LIBCPP_STD_VER >= 20
85bdd1243dSDimitry Andric 
8606c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 14
87fe6060f1SDimitry Andric 
88fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD
89fe6060f1SDimitry Andric 
90fe6060f1SDimitry Andric #endif // _LIBCPP___UTILITY_INTEGER_SEQUENCE_H
91