Skip to content

Do not treat std::array as implicitly reflectable (#169)#234

Open
DuminAndrew wants to merge 1 commit into
boostorg:developfrom
DuminAndrew:fix/169-stdarray-not-reflectable
Open

Do not treat std::array as implicitly reflectable (#169)#234
DuminAndrew wants to merge 1 commit into
boostorg:developfrom
DuminAndrew:fix/169-stdarray-not-reflectable

Conversation

@DuminAndrew

Copy link
Copy Markdown

Problem

boost::pfr::is_implicitly_reflectable_v<std::array<T, N>> evaluates to true
because std::array is an aggregate. But std::array keeps its elements in a
single C array data member, which Boost.PFR can not reflect correctly yet
(#20) — tuple size and per-field access are wrong. Since downstream adaptors
use is_reflectable / is_implicitly_reflectable to decide whether to route a
type through PFR, the trait reporting true makes them mis-handle std::array.

This is the explicit request in #169.

Change

  • Add a detail::is_stdarray trait.
  • Exclude std::array from the implicit reflection branch in
    detail/possible_reflectable.hpp, both with and without
    __cpp_lib_is_aggregate.

The change only affects the is_implicitly_reflectable decision; ordinary
aggregates are unaffected, and no public API is added or removed.

Tests

Extended test/core/run/is_implicitly_reflectable.cpp to assert that
std::array (and its cv-qualified forms) is non-reflectable for both the
boost_json_tag and boost_fusion_tag tags, while plain aggregates stay
reflectable.

Verified locally with g++ 15.2 at cxxstd=14/17/20; the existing
is_reflectable, is_implicitly_reflectable, and tuple_size run-tests
continue to pass.

Closes #169.

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 (boostorg#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 boostorg#169.

namespace boost { namespace pfr { namespace detail {

// std::array<T, N> is an aggregate, but it stores its elements in a C array

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workaround is too specific... How about treating all the types with name array (std::array, boost::array, ...) as non reflectable?

This could be done in the following way:

template <class T>
constexpr std::false_type is_array(int);

template <class T>
constexpr auto is_array(long) -> decltype(std::declval<T>().~array(), std::true_type{});

Call it as decltype(detail::is_array<T>(1L))::value

That way there's no need to include <array> and it would work with boost::array too

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

std::array should not be considered reflectable

3 participants