Skip to content

Commit

Permalink
Skip hand-made aggregate check for non-classes
Browse files Browse the repository at this point in the history
Makes the evaluation of the field count of huge arrays not result in
excessive compiler resource utilization.
  • Loading branch information
runer112 committed Sep 20, 2024
1 parent 5546762 commit 5e655d4
Showing 1 changed file with 10 additions and 10 deletions.
20 changes: 10 additions & 10 deletions include/boost/pfr/detail/fields_count.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ struct is_complete<T, decltype(void(sizeof(T)))> : std::integral_constant<bool,
{};

#ifndef __cpp_lib_is_aggregate
///////////////////// Hand-made is_aggregate_initializable_n<T> trait
///////////////////// Hand-made is_aggregate<T> trait with field count hint N

// Structure that can be converted to reference to anything except reference to T
template <class T, bool IsCopyConstructible>
Expand All @@ -83,25 +83,24 @@ template <class T> struct is_single_field_and_aggregate_initializable<1, T>: std
bool, !std::is_constructible<T, ubiq_constructor_except<T, std::is_copy_constructible<T>::value>>::value
> {};

// Hand-made is_aggregate<T> trait:
// Hand-made is_aggregate<T> trait with field count hint N:
// Before C++20 aggregates could be constructed from `decltype(ubiq_?ref_constructor{I})...` but type traits report that
// there's no constructor from `decltype(ubiq_?ref_constructor{I})...`
// Special case for N == 1: `std::is_constructible<T, ubiq_?ref_constructor>` returns true if N == 1 and T is copy/move constructible.
template <class T, std::size_t N, class /*Enable*/ = void>
struct is_aggregate : std::integral_constant<bool, std::is_array<T>::value>
{};

template <class T, std::size_t N>
struct is_aggregate_initializable_n {
struct is_aggregate<T, N, typename std::enable_if<std::is_class<T>::value>::type> {
template <std::size_t ...I>
static constexpr bool is_not_constructible_n(std::index_sequence<I...>) noexcept {
return (!std::is_constructible<T, decltype(ubiq_lref_constructor{I})...>::value && !std::is_constructible<T, decltype(ubiq_rref_constructor{I})...>::value)
|| is_single_field_and_aggregate_initializable<N, T>::value
;
}

static constexpr bool value =
std::is_empty<T>::value
|| std::is_array<T>::value
|| std::is_fundamental<T>::value
|| is_not_constructible_n(detail::make_index_sequence<N>{})
;
static constexpr bool value = is_not_constructible_n(detail::make_index_sequence<N>{});
};

#endif // #ifndef __cpp_lib_is_aggregate
Expand Down Expand Up @@ -420,7 +419,8 @@ constexpr std::size_t fields_count() noexcept {
#else
constexpr bool postcondition1 =
!preconditions
|| is_aggregate_initializable_n<type, result>::value;
|| detail::is_aggregate<type, result>::value // Does not return `true` for built-in types.
|| std::is_scalar<type>::value;
static_assert(
postcondition1,
"====================> Boost.PFR: Types with user specified constructors (non-aggregate initializable types) are not supported."
Expand Down

0 comments on commit 5e655d4

Please sign in to comment.