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 }