@@ -32,8 +32,7 @@ import std;
32
32
namespace boost { namespace pfr { namespace detail {
33
33
34
34
// /////////////////// min without including <algorithm>
35
- template <class T >
36
- constexpr const T& (min)(const T& a, const T& b) {
35
+ constexpr std::size_t min_of_size_t (std::size_t a, std::size_t b) noexcept {
37
36
return b < a ? b : a;
38
37
}
39
38
@@ -275,17 +274,10 @@ constexpr auto fields_count_upper_bound(long, int) noexcept
275
274
-> detail::enable_if_initializable_helper_t<T, N>
276
275
{
277
276
constexpr std::size_t next_optimal = Begin + (N - Begin) * 2 ;
278
- constexpr std::size_t next = ( detail::min) (next_optimal, detail::fields_count_compiler_limitation_next (N));
277
+ constexpr std::size_t next = detail::min_of_size_t (next_optimal, detail::fields_count_compiler_limitation_next (N));
279
278
return detail::fields_count_upper_bound<T, Begin, next>(1L , 1L );
280
279
}
281
280
282
- template <class T , std::size_t Begin = 0 >
283
- constexpr std::size_t fields_count_binary_search_unbounded () noexcept {
284
- constexpr std::size_t last = detail::fields_count_upper_bound<T, Begin, Begin + 1 >(1L , 1L );
285
- constexpr std::size_t middle = (Begin + last + 1 ) / 2 ;
286
- return detail::fields_count_binary_search<T, Begin, middle>(detail::is_one_element_range<Begin, middle>{}, 1L );
287
- }
288
-
289
281
// /////////////////// Fields count lower bound linear search.
290
282
// Template instantiation: depth is O(log(result)), count is O(result), cost is O(result^2).
291
283
template <class T , std::size_t Begin, std::size_t Last, class RangeSize , std::size_t Result>
@@ -315,13 +307,13 @@ constexpr std::size_t fields_count_lower_bound(detail::multi_element_range, size
315
307
);
316
308
}
317
309
318
- template <class T , std::size_t Begin = 1 , std::size_t Result>
310
+ template <class T , std::size_t Begin, std::size_t Result>
319
311
constexpr std::size_t fields_count_lower_bound_unbounded (int , size_t_<Result>) noexcept {
320
312
return Result;
321
313
}
322
314
323
- template <class T , std::size_t Begin = 1 >
324
- constexpr auto fields_count_lower_bound_unbounded (long , size_t_<0 > = {} ) noexcept
315
+ template <class T , std::size_t Begin, std:: size_t Result >
316
+ constexpr auto fields_count_lower_bound_unbounded (long , size_t_<Result> ) noexcept
325
317
-> std::enable_if_t<(Begin >= detail::fields_count_upper_bound_loose<T>()), std::size_t>
326
318
{
327
319
static_assert (
@@ -330,9 +322,9 @@ constexpr auto fields_count_lower_bound_unbounded(long, size_t_<0> = {}) noexcep
330
322
return detail::fields_count_upper_bound_loose<T>();
331
323
}
332
324
333
- template <class T , std::size_t Begin = 1 >
334
- constexpr std::size_t fields_count_lower_bound_unbounded (int , size_t_<0 > = {} ) noexcept {
335
- constexpr std::size_t last = ( detail::min) (Begin * 2 , detail::fields_count_upper_bound_loose<T>()) - 1 ;
325
+ template <class T , std::size_t Begin>
326
+ constexpr std::size_t fields_count_lower_bound_unbounded (int , size_t_<0 >) noexcept {
327
+ constexpr std::size_t last = detail::min_of_size_t (Begin * 2 , detail::fields_count_upper_bound_loose<T>()) - 1 ;
336
328
constexpr std::size_t result_maybe = detail::fields_count_lower_bound<T, Begin, last>(
337
329
detail::is_one_element_range<Begin, last>{}
338
330
);
@@ -351,15 +343,21 @@ template <class T>
351
343
constexpr auto fields_count_dispatch (long , int ) noexcept
352
344
-> decltype(sizeof (T{}))
353
345
{
354
- return detail::fields_count_binary_search_unbounded<T>();
346
+ constexpr std::size_t typical_fields_count = 4 ;
347
+ constexpr std::size_t last = detail::fields_count_upper_bound<T, typical_fields_count, typical_fields_count * 2 >(1L , 1L );
348
+ constexpr std::size_t middle = (last + 1 ) / 2 ;
349
+ return detail::fields_count_binary_search<T, 0 , middle>(detail::is_one_element_range<0 , middle>{}, 1L );
355
350
}
356
351
357
352
template <class T >
358
353
constexpr std::size_t fields_count_dispatch (int , int ) noexcept {
359
354
// T is not default aggregate initializable. This means that at least one of the members is not default-constructible.
360
355
// Use linear search to find the smallest valid initializer, after which we unbounded binary search for the largest.
361
- constexpr std::size_t begin = detail::fields_count_lower_bound_unbounded<T>(1L );
362
- return detail::fields_count_binary_search_unbounded<T, begin>();
356
+ constexpr std::size_t begin = detail::fields_count_lower_bound_unbounded<T, 1 >(1L , size_t_<0 >{});
357
+
358
+ constexpr std::size_t last = detail::fields_count_upper_bound<T, begin, begin + 1 >(1L , 1L );
359
+ constexpr std::size_t middle = (begin + last + 1 ) / 2 ;
360
+ return detail::fields_count_binary_search<T, begin, middle>(detail::is_one_element_range<begin, middle>{}, 1L );
363
361
}
364
362
365
363
// /////////////////// Returns fields count
0 commit comments