]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | // |
b32b8144 | 2 | // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) |
7c673cae FG |
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 | // | |
b32b8144 FG |
7 | // Official repository: https://github.com/boostorg/beast |
8 | // | |
7c673cae | 9 | |
b32b8144 FG |
10 | #ifndef BOOST_BEAST_DETAIL_INTEGER_SEQUENCE_HPP |
11 | #define BOOST_BEAST_DETAIL_INTEGER_SEQUENCE_HPP | |
7c673cae | 12 | |
b32b8144 | 13 | #include <boost/config.hpp> |
7c673cae FG |
14 | #include <cstddef> |
15 | #include <type_traits> | |
16 | #include <utility> | |
17 | ||
b32b8144 | 18 | namespace boost { |
7c673cae FG |
19 | namespace beast { |
20 | namespace detail { | |
21 | ||
22 | template<class T, T... Ints> | |
23 | struct integer_sequence | |
24 | { | |
25 | using value_type = T; | |
b32b8144 | 26 | BOOST_STATIC_ASSERT(std::is_integral<T>::value); |
7c673cae FG |
27 | |
28 | static std::size_t constexpr static_size = sizeof...(Ints); | |
29 | ||
30 | static std::size_t constexpr size() | |
31 | { | |
32 | return sizeof...(Ints); | |
33 | } | |
34 | }; | |
35 | ||
36 | template<std::size_t... Ints> | |
37 | using index_sequence = integer_sequence<std::size_t, Ints...>; | |
38 | ||
39 | // This workaround is needed for broken sizeof... | |
40 | template<class... Args> | |
41 | struct sizeof_workaround | |
42 | { | |
43 | static std::size_t constexpr size = sizeof... (Args); | |
44 | }; | |
45 | ||
b32b8144 | 46 | #ifdef BOOST_MSVC |
7c673cae | 47 | |
b32b8144 | 48 | // This implementation compiles on real MSVC and clang but not gcc |
7c673cae FG |
49 | |
50 | template<class T, unsigned long long N, class Seq> | |
51 | struct make_integer_sequence_unchecked; | |
52 | ||
53 | template<class T, unsigned long long N, unsigned long long ...Indices> | |
54 | struct make_integer_sequence_unchecked< | |
55 | T, N, integer_sequence<T, Indices...>> | |
56 | { | |
57 | using type = typename make_integer_sequence_unchecked< | |
58 | T, N-1, integer_sequence<T, N-1, Indices...>>::type; | |
59 | }; | |
60 | ||
61 | template<class T, unsigned long long ...Indices> | |
62 | struct make_integer_sequence_unchecked< | |
63 | T, 0, integer_sequence<T, Indices...>> | |
64 | { | |
65 | using type = integer_sequence<T, Indices...>; | |
66 | }; | |
67 | ||
68 | template<class T, T N> | |
69 | struct make_integer_sequence_checked | |
70 | { | |
b32b8144 FG |
71 | BOOST_STATIC_ASSERT(std::is_integral<T>::value); |
72 | BOOST_STATIC_ASSERT(N >= 0); | |
7c673cae FG |
73 | |
74 | using type = typename make_integer_sequence_unchecked< | |
75 | T, N, integer_sequence<T>>::type; | |
76 | }; | |
77 | ||
78 | template<class T, T N> | |
79 | using make_integer_sequence = | |
80 | typename make_integer_sequence_checked<T, N>::type; | |
81 | ||
82 | template<std::size_t N> | |
83 | using make_index_sequence = make_integer_sequence<std::size_t, N>; | |
84 | ||
85 | template<class... Args> | |
86 | using index_sequence_for = | |
87 | make_index_sequence<sizeof_workaround<Args...>::size>; | |
88 | ||
89 | #else | |
90 | ||
91 | // This implementation compiles on gcc but not MSVC | |
92 | ||
93 | template<std::size_t... Ints> | |
94 | struct index_tuple | |
95 | { | |
96 | using next = index_tuple<Ints..., sizeof... (Ints)>; | |
97 | ||
98 | }; | |
99 | ||
100 | template<std::size_t N> | |
101 | struct build_index_tuple | |
102 | { | |
103 | using type = typename build_index_tuple<N-1>::type::next; | |
104 | }; | |
105 | ||
106 | template<> | |
107 | struct build_index_tuple<0> | |
108 | { | |
109 | using type = index_tuple<>; | |
110 | }; | |
111 | ||
112 | template<class T, T N, | |
113 | class Seq = typename build_index_tuple<N>::type | |
114 | > | |
115 | struct integer_sequence_helper; | |
116 | ||
117 | template<class T, T N, std::size_t... Ints> | |
118 | struct integer_sequence_helper<T, N, index_tuple<Ints...>> | |
119 | { | |
b32b8144 FG |
120 | BOOST_STATIC_ASSERT(std::is_integral<T>::value); |
121 | BOOST_STATIC_ASSERT(N >= 0); | |
7c673cae FG |
122 | |
123 | using type = integer_sequence<T, static_cast<T> (Ints)...>; | |
124 | }; | |
125 | ||
126 | template<class T, T N> | |
127 | using make_integer_sequence = | |
128 | typename integer_sequence_helper<T, N>::type; | |
129 | ||
130 | template<std::size_t N> | |
131 | using make_index_sequence = make_integer_sequence<std::size_t, N>; | |
132 | ||
133 | template<class... Args> | |
134 | using index_sequence_for = | |
135 | make_index_sequence<sizeof_workaround<Args...>::size>; | |
136 | ||
137 | #endif | |
138 | ||
139 | } // detail | |
140 | } // beast | |
b32b8144 | 141 | } // boost |
7c673cae FG |
142 | |
143 | #endif |