From 8e880be2ace28dd719e3410e6694a63c04d31cf5 Mon Sep 17 00:00:00 2001 From: DuminAndrew Date: Sat, 30 May 2026 13:15:26 +0700 Subject: [PATCH] fix: do not treat std::array as implicitly reflectable std::array is an aggregate, so is_implicitly_reflectable_v reported it as reflectable. However, std::array stores its elements in a single C array member, which Boost.PFR can not reflect correctly yet (#20): the field count and per-field access are wrong. Downstream users of is_reflectable therefore mis-handle std::array. Exclude std::array from the implicit reflection decision via a dedicated detail::is_stdarray trait, so is_implicitly_reflectable reports false for it and its cv-qualified variants. Other aggregates are unaffected. Closes #169. --- .../boost/pfr/detail/possible_reflectable.hpp | 18 +++++++++++++++--- test/core/run/is_implicitly_reflectable.cpp | 11 +++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/include/boost/pfr/detail/possible_reflectable.hpp b/include/boost/pfr/detail/possible_reflectable.hpp index 2da06467..1a1a0f05 100644 --- a/include/boost/pfr/detail/possible_reflectable.hpp +++ b/include/boost/pfr/detail/possible_reflectable.hpp @@ -11,11 +11,23 @@ #include #if !defined(BOOST_PFR_INTERFACE_UNIT) +#include // for std::array +#include // for std::size_t #include // for std::is_aggregate #endif namespace boost { namespace pfr { namespace detail { +// std::array is an aggregate, but it stores its elements in a C array +// data member. Boost.PFR can not reflect types with C array members yet (see +// https://github.com/boostorg/pfr/issues/20), so std::array must not be +// treated as implicitly reflectable. +template +struct is_stdarray : std::false_type {}; + +template +struct is_stdarray> : std::true_type {}; + ///////////////////// Returns false when the type exactly wasn't be reflectable template constexpr decltype(is_reflectable::value) possible_reflectable(long) noexcept { @@ -26,11 +38,11 @@ constexpr decltype(is_reflectable::value) possible_reflectable(long) template constexpr bool possible_reflectable(int) noexcept { -# if defined(__cpp_lib_is_aggregate) using type = std::remove_cv_t; - return std::is_aggregate(); +# if defined(__cpp_lib_is_aggregate) + return std::is_aggregate() && !detail::is_stdarray::value; # else - return true; + return !detail::is_stdarray::value; # endif } diff --git a/test/core/run/is_implicitly_reflectable.cpp b/test/core/run/is_implicitly_reflectable.cpp index 0dc9879a..f444710c 100644 --- a/test/core/run/is_implicitly_reflectable.cpp +++ b/test/core/run/is_implicitly_reflectable.cpp @@ -3,6 +3,7 @@ // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#include #include #include #include // for std::true_type, std::false_type and std::is_aggregate @@ -71,6 +72,12 @@ int main() { assert_non_reflectable(); assert_reflectable(); assert_non_reflectable(); + + // std::array is an aggregate, but it holds a C array member that + // Boost.PFR can not reflect correctly, so it must not be considered + // implicitly reflectable (https://github.com/boostorg/pfr/issues/169). + assert_non_reflectable, tag>(); + assert_non_reflectable, tag>(); } { @@ -81,6 +88,10 @@ int main() { assert_non_reflectable(); assert_reflectable(); assert_non_reflectable(); + + // See the comment in the boost_json_tag block above. + assert_non_reflectable, tag>(); + assert_non_reflectable, tag>(); } #endif // #if BOOST_PFR_ENABLE_IMPLICIT_REFLECTION }