@@ -68,82 +68,182 @@ BOOST_HANA_NAMESPACE_BEGIN
6868 ));
6969 };
7070
71- template <typename Pred, std::size_t Insert, bool IsInsertionPoint,
72- typename Left,
73- std::size_t ...Right>
74- struct insert ;
71+ template <typename Left, typename Right>
72+ struct concat ;
73+
74+ template <std::size_t ...l, std::size_t ...r>
75+ struct concat <std::index_sequence<l...>, std::index_sequence<r...>> {
76+ using type = std::index_sequence<l..., r...>;
77+ };
78+
79+ template <typename Pred, bool PickRight, typename Left, typename Right>
80+ struct merge ;
7581
76- // We did not find the insertion point; continue processing elements
77- // recursively.
7882 template <
79- typename Pred, std::size_t Insert,
80- std::size_t ...Left,
81- std::size_t Right1, std::size_t Right2, std::size_t ...Right
82- >
83- struct insert <Pred, Insert, false ,
84- std::index_sequence<Left...>,
85- Right1, Right2, Right...
83+ typename Pred,
84+ std::size_t l0,
85+ std::size_t l1,
86+ std::size_t ...l,
87+ std::size_t r0,
88+ std::size_t ...r>
89+ struct merge <
90+ Pred,
91+ false ,
92+ std::index_sequence<l0, l1, l...>,
93+ std::index_sequence<r0, r...>
8694 > {
87- using type = typename insert<
88- Pred, Insert, (bool )Pred::template apply<Insert, Right2>::value,
89- std::index_sequence<Left..., Right1>,
90- Right2, Right...
95+ using type = typename concat<
96+ std::index_sequence<l0>,
97+ typename merge<
98+ Pred,
99+ (bool )Pred::template apply<r0, l1>::value,
100+ std::index_sequence<l1, l...>,
101+ std::index_sequence<r0, r...>
102+ >::type
91103 >::type;
92104 };
93105
94- // We did not find the insertion point, but there is only one element
95- // left. We insert at the end of the list, and we're done.
96- template <typename Pred, std::size_t Insert, std::size_t ...Left, std::size_t Last>
97- struct insert <Pred, Insert, false , std::index_sequence<Left...>, Last> {
98- using type = std::index_sequence<Left..., Last, Insert>;
106+ template <
107+ typename Pred,
108+ std::size_t l0,
109+ std::size_t r0,
110+ std::size_t ...r>
111+ struct merge <
112+ Pred,
113+ false ,
114+ std::index_sequence<l0>,
115+ std::index_sequence<r0, r...>
116+ > {
117+ using type = std::index_sequence<l0, r0, r...>;
99118 };
100119
101- // We found the insertion point, we're done.
102- template <typename Pred, std::size_t Insert, std::size_t ...Left, std::size_t ...Right>
103- struct insert <Pred, Insert, true , std::index_sequence<Left...>, Right...> {
104- using type = std::index_sequence<Left..., Insert, Right...>;
120+ template <
121+ typename Pred,
122+ std::size_t l0,
123+ std::size_t ...l,
124+ std::size_t r0,
125+ std::size_t r1,
126+ std::size_t ...r>
127+ struct merge <
128+ Pred,
129+ true ,
130+ std::index_sequence<l0, l...>,
131+ std::index_sequence<r0, r1, r...>
132+ > {
133+ using type = typename concat<
134+ std::index_sequence<r0>,
135+ typename merge<
136+ Pred,
137+ (bool )Pred::template apply<r1, l0>::value,
138+ std::index_sequence<l0, l...>,
139+ std::index_sequence<r1, r...>
140+ >::type
141+ >::type;
105142 };
106143
144+ template <
145+ typename Pred,
146+ std::size_t l0,
147+ std::size_t ...l,
148+ std::size_t r0>
149+ struct merge <
150+ Pred,
151+ true ,
152+ std::index_sequence<l0, l...>,
153+ std::index_sequence<r0>
154+ > {
155+ using type = std::index_sequence<r0, l0, l...>;
156+ };
107157
108- template <typename Pred, typename Result, std:: size_t ...T >
109- struct insertion_sort_impl ;
158+ template <typename Pred, typename Left, typename Right >
159+ struct merge_helper ;
110160
111- template <typename Pred,
112- std::size_t Result1, std::size_t ...Result,
113- std::size_t T, std::size_t ...Ts>
114- struct insertion_sort_impl <Pred, std::index_sequence<Result1, Result...>, T, Ts...> {
115- using type = typename insertion_sort_impl<
161+ template <
162+ typename Pred,
163+ std::size_t l0,
164+ std::size_t ...l,
165+ std::size_t r0,
166+ std::size_t ...r>
167+ struct merge_helper <
168+ Pred,
169+ std::index_sequence<l0, l...>,
170+ std::index_sequence<r0, r...>
171+ > {
172+ using type = typename merge<
116173 Pred,
117- typename insert<
118- Pred, T, (bool )Pred::template apply<T, Result1>::value,
119- std::index_sequence<>,
120- Result1, Result...
121- >::type,
122- Ts...
174+ (bool )Pred::template apply<r0, l0>::value,
175+ std::index_sequence<l0, l...>,
176+ std::index_sequence<r0, r...>
123177 >::type;
124178 };
125179
126- template <typename Pred, std::size_t T, std::size_t ...Ts>
127- struct insertion_sort_impl <Pred, std::index_sequence<>, T, Ts...> {
128- using type = typename insertion_sort_impl<
129- Pred, std::index_sequence<T>, Ts...
130- >::type;
180+ // split templated structure, Nr represents the number of elements
181+ // from Right to move to Left
182+ // There are two specializations:
183+ // The first handles the generic case (Nr > 0)
184+ // The second handles the stop condition (Nr == 0)
185+ // These two specializations are not strictly ordered as
186+ // the first cannot match Nr==0 && empty Right
187+ // the second cannot match Nr!=0
188+ // std::enable_if<Nr!=0> is therefore required to make sure these two
189+ // specializations will never both be candidates during an overload
190+ // resolution (otherwise ambiguity occurs for Nr==0 and non-empty Right)
191+ template <std::size_t Nr, typename Left, typename Right, typename =void >
192+ struct split ;
193+
194+ template <
195+ std::size_t Nr,
196+ std::size_t ...l,
197+ std::size_t ...r,
198+ std::size_t r0>
199+ struct split <
200+ Nr,
201+ std::index_sequence<l...>,
202+ std::index_sequence<r0, r...>,
203+ typename std::enable_if<Nr!=0 >::type
204+ > {
205+ using sp = split<
206+ Nr-1 ,
207+ std::index_sequence<l..., r0>,
208+ std::index_sequence<r...>
209+ >;
210+ using left = typename sp::left;
211+ using right = typename sp::right;
131212 };
132213
133- template <typename Pred, typename Result>
134- struct insertion_sort_impl <Pred, Result> {
135- using type = Result;
214+ template <std::size_t ...l, std::size_t ...r>
215+ struct split <0 , std::index_sequence<l...>, std::index_sequence<r...>> {
216+ using left = std::index_sequence<l...>;
217+ using right = std::index_sequence<r...>;
136218 };
137219
138- template <typename Pred, typename Indices >
139- struct sort_helper ;
220+ template <typename Pred, typename Sequence >
221+ struct merge_sort_impl ;
140222
141- template <typename Pred, std::size_t ...i>
142- struct sort_helper <Pred, std::index_sequence<i...>> {
143- using type = typename insertion_sort_impl<
144- Pred, std::index_sequence<>, i...
223+ template <typename Pred, std::size_t ...seq>
224+ struct merge_sort_impl <Pred, std::index_sequence<seq...>> {
225+ using sequence = std::index_sequence<seq...>;
226+ using sp = split<
227+ sequence::size () / 2 ,
228+ std::index_sequence<>,
229+ sequence
230+ >;
231+ using type = typename merge_helper<
232+ Pred,
233+ typename merge_sort_impl<Pred, typename sp::left>::type,
234+ typename merge_sort_impl<Pred, typename sp::right>::type
145235 >::type;
146236 };
237+
238+ template <typename Pred, std::size_t x>
239+ struct merge_sort_impl <Pred, std::index_sequence<x>> {
240+ using type = std::index_sequence<x>;
241+ };
242+
243+ template <typename Pred>
244+ struct merge_sort_impl <Pred, std::index_sequence<>> {
245+ using type = std::index_sequence<>;
246+ };
147247 } // end namespace detail
148248
149249 template <typename S, bool condition>
@@ -156,7 +256,7 @@ BOOST_HANA_NAMESPACE_BEGIN
156256 template <typename Xs, typename Pred>
157257 static constexpr auto apply (Xs&& xs, Pred const &) {
158258 constexpr std::size_t Len = decltype (hana::length (xs))::value;
159- using Indices = typename detail::sort_helper <
259+ using Indices = typename detail::merge_sort_impl <
160260 detail::sort_predicate<Xs&&, Pred>,
161261 std::make_index_sequence<Len>
162262 >::type;
0 commit comments