]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com) | |
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 | // | |
7 | ||
8 | #ifndef BEAST_DETAIL_INTEGER_SEQUENCE_H_INCLUDED | |
9 | #define BEAST_DETAIL_INTEGER_SEQUENCE_H_INCLUDED | |
10 | ||
11 | #include <cstddef> | |
12 | #include <type_traits> | |
13 | #include <utility> | |
14 | ||
15 | namespace beast { | |
16 | namespace detail { | |
17 | ||
18 | template<class T, T... Ints> | |
19 | struct integer_sequence | |
20 | { | |
21 | using value_type = T; | |
22 | static_assert (std::is_integral<T>::value, | |
23 | "std::integer_sequence can only be instantiated with an integral type" ); | |
24 | ||
25 | static std::size_t constexpr static_size = sizeof...(Ints); | |
26 | ||
27 | static std::size_t constexpr size() | |
28 | { | |
29 | return sizeof...(Ints); | |
30 | } | |
31 | }; | |
32 | ||
33 | template<std::size_t... Ints> | |
34 | using index_sequence = integer_sequence<std::size_t, Ints...>; | |
35 | ||
36 | // This workaround is needed for broken sizeof... | |
37 | template<class... Args> | |
38 | struct sizeof_workaround | |
39 | { | |
40 | static std::size_t constexpr size = sizeof... (Args); | |
41 | }; | |
42 | ||
43 | #ifdef _MSC_VER | |
44 | ||
45 | // This implementation compiles on MSVC and clang but not gcc | |
46 | ||
47 | template<class T, unsigned long long N, class Seq> | |
48 | struct make_integer_sequence_unchecked; | |
49 | ||
50 | template<class T, unsigned long long N, unsigned long long ...Indices> | |
51 | struct make_integer_sequence_unchecked< | |
52 | T, N, integer_sequence<T, Indices...>> | |
53 | { | |
54 | using type = typename make_integer_sequence_unchecked< | |
55 | T, N-1, integer_sequence<T, N-1, Indices...>>::type; | |
56 | }; | |
57 | ||
58 | template<class T, unsigned long long ...Indices> | |
59 | struct make_integer_sequence_unchecked< | |
60 | T, 0, integer_sequence<T, Indices...>> | |
61 | { | |
62 | using type = integer_sequence<T, Indices...>; | |
63 | }; | |
64 | ||
65 | template<class T, T N> | |
66 | struct make_integer_sequence_checked | |
67 | { | |
68 | static_assert (std::is_integral<T>::value, | |
69 | "T must be an integral type"); | |
70 | ||
71 | static_assert (N >= 0, | |
72 | "N must be non-negative"); | |
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 | { | |
120 | static_assert (std::is_integral<T>::value, | |
121 | "T must be an integral type"); | |
122 | ||
123 | static_assert (N >= 0, | |
124 | "N must be non-negative"); | |
125 | ||
126 | using type = integer_sequence<T, static_cast<T> (Ints)...>; | |
127 | }; | |
128 | ||
129 | template<class T, T N> | |
130 | using make_integer_sequence = | |
131 | typename integer_sequence_helper<T, N>::type; | |
132 | ||
133 | template<std::size_t N> | |
134 | using make_index_sequence = make_integer_sequence<std::size_t, N>; | |
135 | ||
136 | template<class... Args> | |
137 | using index_sequence_for = | |
138 | make_index_sequence<sizeof_workaround<Args...>::size>; | |
139 | ||
140 | #endif | |
141 | ||
142 | } // detail | |
143 | } // beast | |
144 | ||
145 | #endif |