1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
|
/**
* \file
* \brief IntegerSequence template class header
*
* \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
*
* \par License
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
* distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef ESTD_INTEGERSEQUENCE_HPP_
#define ESTD_INTEGERSEQUENCE_HPP_
#include <type_traits>
namespace estd
{
/**
* \brief Compile-time sequence of integers
*
* Similar to std::integer_sequence from C++14 - http://en.cppreference.com/w/cpp/utility/integer_sequence
*
* \tparam T is an integer type to use for the elements of the sequence
* \tparam Integers is a non-type parameter pack representing the sequence
*/
template<typename T, T... Integers>
class IntegerSequence
{
public:
/// integer type used for the elements of the sequence
using value_type = T;
/**
* \return number of elements in the sequence
*/
constexpr static std::size_t size() noexcept
{
return sizeof...(Integers);
};
};
/**
* \brief Compile-time sequence of std::size_t elements
*
* Similar to std::index_sequence from C++14 - http://en.cppreference.com/w/cpp/utility/integer_sequence
*
* \tparam Indexes is a non-type parameter pack representing the sequence
*/
template<std::size_t... Indexes>
using IndexSequence = IntegerSequence<std::size_t, Indexes...>;
namespace internal
{
/**
* \brief IntegerSequence with two internal type aliases.
*
* \tparam T is an integer type to use for the elements of the sequence
* \tparam Integers is a non-type parameter pack representing the sequence
*/
template<typename T, T... Integers>
struct TypedSequence : IntegerSequence<T, Integers...>
{
/// type of base class
using base = IntegerSequence<T, Integers...>;
/// type of class
using type = TypedSequence;
};
/**
* \brief TypedSequence with doubled number of elements
*
* \tparam Sequence is the type of sequence that will be doubled
*/
template<typename Sequence>
struct DoubledIntegerSequence;
/**
* \brief TypedSequence with doubled number of elements
*
* Specialization for TypedSequence.
*
* \tparam T is an integer type to use for the elements of the sequence
* \tparam Integers is a non-type parameter pack representing the sequence
*/
template<typename T, T... Integers>
struct DoubledIntegerSequence<TypedSequence<T, Integers...>>
{
/// TypedSequence with doubled number of elements - TypedSequence<T, 0, 1, ..., N - 1> is turned into
/// TypedSequence<T, 0, 1, ..., N - 1, N, N + 1, ..., 2 * N - 1>
using type = TypedSequence<T, Integers..., (sizeof...(Integers) + Integers)...>;
};
/**
* \brief TypedSequence optionally extended by one element
*
* \tparam Extend selects whether the sequence will be extended by one element (true) or not (false)
* \tparam Sequence is the type of sequence that will optionally be extended
*/
template<bool Extend, typename Sequence>
struct ExtendedIntegerSequence
{
/// same as \a Sequence
using type = Sequence;
};
/**
* \brief TypedSequence optionally extended by one element
*
* Specialization for the case with extending.
*
* \tparam T is an integer type to use for the elements of the sequence
* \tparam Integers is a non-type parameter pack representing the sequence
*/
template<typename T, T... Integers>
struct ExtendedIntegerSequence<true, TypedSequence<T, Integers...>>
{
/// sequence extended by one element - TypedSequence<T, 0, 1, ..., N - 1> is turned into
/// TypedSequence<T, 0, 1, ..., N - 1, N>
using type = TypedSequence<T, Integers..., sizeof...(Integers)>;
};
/**
* \brief Implementation of generator of IntegerSequence types
*
* Generates TypedSequence<T, 0, 1, ..., N - 1> type.
*
* \tparam T is an integer type to use for the elements of the sequence
* \tparam N is the requested number of elements in the sequence
*/
template<typename T, std::size_t N>
struct MakeIntegerSequenceImplementation :
ExtendedIntegerSequence<N % 2 != 0,
typename DoubledIntegerSequence<typename MakeIntegerSequenceImplementation<T, N / 2>::type>::type>
{
};
/**
* \brief Implementation of generator of IntegerSequence types
*
* Specialization for terminal case - 0 elements - generates TypedSequence<T> type.
*
* \tparam T is an integer type to use for the elements of the sequence
*/
template<typename T>
struct MakeIntegerSequenceImplementation<T, 0>
{
/// empty TypedSequence<T> type
using type = TypedSequence<T>;
};
/**
* \brief Wrapper for MakeIntegerSequenceImplementation that ensures \a N is non-negative
*
* Generates TypedSequence<T, 0, 1, ..., N - 1> type.
*
* \tparam T is an integer type to use for the elements of the sequence
* \tparam N is the requested number of elements in the sequence, must be non-negative
*/
template<typename T, T N>
struct MakeIntegerSequenceImplementationWrapper :
std::enable_if<N >= 0, MakeIntegerSequenceImplementation<T, static_cast<std::size_t>(N)>>::type
{
static_assert(N >= 0, "Number of elements in the sequence must be non-negative!");
};
} // namespace internal
/**
* \brief Generator of IntegerSequence types
*
* Similar to std::make_integer_sequence from C++14 - http://en.cppreference.com/w/cpp/utility/integer_sequence
*
* Whole implementation is based on code from http://stackoverflow.com/a/20101039/157344
*
* Generates IntegerSequence<T, 0, 1, ..., N - 1> type.
*
* \tparam T is an integer type to use for the elements of the sequence
* \tparam N is the requested number of elements in the sequence
*/
template<typename T, T N>
using MakeIntegerSequence = typename internal::MakeIntegerSequenceImplementationWrapper<T, N>::type::base;
/**
* \brief Generator of IndexSequence types
*
* Similar to std::make_index_sequence from C++14 - http://en.cppreference.com/w/cpp/utility/integer_sequence
*
* Generates IndexSequence<0, 1, ..., N - 1> type.
*
* \tparam N is the requested number of elements in the sequence
*/
template<std::size_t N>
using MakeIndexSequence = MakeIntegerSequence<std::size_t, N>;
/**
* \brief Generator of IndexSequence types
*
* Similar to std::index_sequence_for from C++14 - http://en.cppreference.com/w/cpp/utility/integer_sequence
*
* Generates IndexSequence<0, 1, ..., sizeof...(T) - 1> type.
*
* \tparam T is the type parameter pack for which an index sequence of the same length will be generated
*/
template<typename... T>
using IndexSequenceFor = MakeIndexSequence<sizeof...(T)>;
} // namespace estd
#endif // ESTD_INTEGERSEQUENCE_HPP_
|