make_integer_sequence.hpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. // Copyright (c) 2018 Sergei Fedorov
  2. // Copyright (c) 2019-2021 Antony Polukhin
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_PFR_DETAIL_MAKE_INTEGER_SEQUENCE_HPP
  7. #define BOOST_PFR_DETAIL_MAKE_INTEGER_SEQUENCE_HPP
  8. #pragma once
  9. #include <boost/pfr/detail/config.hpp>
  10. #include <type_traits>
  11. #include <utility>
  12. #include <cstddef>
  13. namespace boost { namespace pfr { namespace detail {
  14. #if BOOST_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE == 0
  15. #ifdef __has_builtin
  16. # if __has_builtin(__make_integer_seq)
  17. # define BOOST_PFR_USE_MAKE_INTEGER_SEQ_BUILTIN
  18. # endif
  19. #endif
  20. #ifdef BOOST_PFR_USE_MAKE_INTEGER_SEQ_BUILTIN
  21. using std::integer_sequence;
  22. // Clang unable to use namespace qualified std::integer_sequence in __make_integer_seq.
  23. template <typename T, T N>
  24. using make_integer_sequence = __make_integer_seq<integer_sequence, T, N>;
  25. #undef BOOST_PFR_USE_MAKE_INTEGER_SEQ_BUILTIN
  26. #else
  27. template <typename T, typename U>
  28. struct join_sequences;
  29. template <typename T, T... A, T... B>
  30. struct join_sequences<std::integer_sequence<T, A...>, std::integer_sequence<T, B...>> {
  31. using type = std::integer_sequence<T, A..., B...>;
  32. };
  33. template <typename T, T Min, T Max>
  34. struct build_sequence_impl {
  35. static_assert(Min < Max, "Start of range must be less than its end");
  36. static constexpr T size = Max - Min;
  37. using type = typename join_sequences<
  38. typename build_sequence_impl<T, Min, Min + size / 2>::type,
  39. typename build_sequence_impl<T, Min + size / 2 + 1, Max>::type
  40. >::type;
  41. };
  42. template <typename T, T V>
  43. struct build_sequence_impl<T, V, V> {
  44. using type = std::integer_sequence<T, V>;
  45. };
  46. template <typename T, std::size_t N>
  47. struct make_integer_sequence_impl : build_sequence_impl<T, 0, N - 1> {};
  48. template <typename T>
  49. struct make_integer_sequence_impl<T, 0> {
  50. using type = std::integer_sequence<T>;
  51. };
  52. template <typename T, T N>
  53. using make_integer_sequence = typename make_integer_sequence_impl<T, N>::type;
  54. #endif // !defined BOOST_PFR_USE_MAKE_INTEGER_SEQ_BUILTIN
  55. #else // BOOST_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE == 1
  56. template <typename T, T N>
  57. using make_integer_sequence = std::make_integer_sequence<T, N>;
  58. #endif // BOOST_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE == 1
  59. template <std::size_t N>
  60. using make_index_sequence = make_integer_sequence<std::size_t, N>;
  61. template <typename... T>
  62. using index_sequence_for = make_index_sequence<sizeof...(T)>;
  63. }}} // namespace boost::pfr::detail
  64. #endif