diff --git a/include/simdjson/generic/ondemand/std_deserialize.h b/include/simdjson/generic/ondemand/std_deserialize.h index 555e5921d..5ced0e343 100644 --- a/include/simdjson/generic/ondemand/std_deserialize.h +++ b/include/simdjson/generic/ondemand/std_deserialize.h @@ -310,6 +310,21 @@ template using selector_for = typename [: std::meta::substitute( ^^SIMDJSON_IMPLEMENTATION::ondemand::key_selector, selector_key_args()) :]; +// Number of members that participate in deserialization. A class can have zero +// eligible members (e.g. std::chrono::time_point, whose only data member is +// private): an empty key_selector cannot be built, so the tag_invoke below +// special-cases this count. +template +consteval std::size_t eligible_member_count() { + std::size_t count = 0; + template for (constexpr auto mem : std::define_static_array(std::meta::nonstatic_data_members_of(^^T, std::meta::access_context::unchecked()))) { + if constexpr (is_eligible_member(mem)) { + ++count; + } + } + return count; +} + // True when none of T's eligible members is an optional type, i.e. every member // is required. In that case presence can be checked with a single match count // instead of a per-member "seen" array. @@ -337,6 +352,14 @@ error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept { } else { SIMDJSON_TRY(val.get_object().get(obj)); } + if constexpr (key_selector_reflection_detail::eligible_member_count() == 0) { + // No members to deserialize: an empty key_selector cannot be built, so just + // validate that the input is an object (done above) and succeed. Mirrors the + // opt-out per-member path, which iterates over zero members. + (void)out; + (void)obj; + return SUCCESS; + } else { using selector = key_selector_reflection_detail::selector_for; if constexpr (key_selector_reflection_detail::all_eligible_members_required()) { // Fast path: every member is required. A single for_each pass parses each @@ -395,6 +418,7 @@ error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept { } return SUCCESS; } + } } #else