boostorg / pfr

std::tuple like methods for user defined types without any macro or boilerplate code
https://boost.org/libs/pfr
Boost Software License 1.0
1.32k stars 157 forks source link

Feature request: for_each_field multiple visitation #69

Open invexed opened 3 years ago

invexed commented 3 years ago

Multiple visitation is easy enough to achieve with a library like Boost.Hana (see below), but I think it would be useful functionality for for_each_field to support directly.

template<typename Invocable, typename... Aggregates>
constexpr auto for_each_field(Invocable f, Aggregates&&... xs) -> void
{
    namespace hana = boost::hana;
    hana::for_each(hana::zip(boost::pfr::structure_tie(xs)...), hana::fuse(std::move(f)));
}

Example on Compiler Explorer

invexed commented 3 years ago

boost::hana::zip_with and std::forward_as_tuple would prevent unnecessary copies occurring when constructing the inner tuples.

SpriteOvO commented 3 years ago

pfr::structure_tie with parameter pack will cause an "internal compiler error" in the current latest MSVC, for those who are having this problem or don't want to use hana, the following workaround also works:

template <size_t index = 0, class ...Args>
void ForEachMultipleFields(const auto &callback, Args &&...args)
{
    callback(pfr::get<index>(args)...);

    constexpr size_t size = pfr::detail::fields_count<
        std::decay_t<std::tuple_element_t<0, std::tuple<Args...>>>
    >();
    if constexpr (index + 1 != size) {
        ForEachMultipleFields<index + 1>(callback, std::forward<Args>(args)...);
    }
}

Example