You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Boost.Pfr是否支持以成员指针形式遍历类型的字段

结论

Boost.Pfr 原生提供的 boost::pfr::for_each_field 接口仅会将遍历到的字段以引用形式传入回调,没有内置直接传递 T A::* 类型类成员指针的功能。但你完全可以基于Pfr已有的编译期反射能力,用少量代码实现符合你预期的用法,没有额外运行时开销,和原生接口的适用范围完全一致。

Pfr遍历字段的核心逻辑是基于编译期索引展开:你可以通过boost::pfr::tuple_size_v<T>拿到类型的字段总数,通过boost::pfr::tuple_element_t<I, T>拿到第I个字段的类型,再通过标准语法构造出对应位置的成员指针即可。


可直接复用的实现代码

#include <boost/pfr.hpp>
#include <string>
#include <utility>
#include <type_traits>

struct A {
    int number;
    std::string text;
};

// 编译期索引展开辅助实现
template <typename T, typename F, std::size_t... Is>
void for_each_field_mem_ptr_impl(T&& obj, F&& f, std::index_sequence<Is...>) {
    using unqualified_T = std::remove_cvref_t<T>;
    // 按索引构造对应类型的成员指针,传入回调
    (f(
        static_cast<boost::pfr::tuple_element_t<Is, unqualified_T> unqualified_T::*>(
            &boost::pfr::get<Is>(std::declval<unqualified_T&>())
        ),
        boost::pfr::get<Is>(std::forward<T>(obj)) // 如果不需要同时拿到字段引用可以删掉这行
    ), ...);
}

// 对外接口,用法和boost::pfr::for_each_field对齐
template <typename T, typename F>
void for_each_field_mem_ptr(T&& obj, F&& f) {
    using unqualified_T = std::remove_cvref_t<T>;
    for_each_field_mem_ptr_impl(
        std::forward<T>(obj),
        std::forward<F>(f),
        std::make_index_sequence<boost::pfr::tuple_size_v<unqualified_T>>{}
    );
}

使用示例(完全匹配你期望的写法)

int main() {
    for_each_field_mem_ptr(A{1, "foo"},
        [](auto A::* field, auto& field_value) {
            // 这里的field就是你需要的T A::*类型成员指针
            // field_value是对应字段的引用,不需要可以在实现里删掉
            A test_obj{42, "bar"};
            auto& val = test_obj.*field; // 直接通过成员指针访问
        }
    );

    // 正确性验证:生成的成员指针和手动取的成员地址完全一致
    for_each_field_mem_ptr(A{1, "foo"},
        [](auto A::* field, auto&) {
            if constexpr (std::is_same_v<decltype(field), int A::*>) {
                static_assert(&A::number == field);
            }
            if constexpr (std::is_same_v<decltype(field), std::string A::*>) {
                static_assert(&A::text == field);
            }
        }
    );
}

注意事项

  • 该实现仅对Boost.Pfr支持的聚合类型生效,即所有非静态成员均为公有、无用户声明构造函数的聚合类型,和原生for_each_field的适配范围完全相同。
  • 整个逻辑在编译期完成展开,运行时无任何额外开销,生成的成员指针和你手动写&A::number、&A::text得到的指针完全一致,可以直接通过.*/->*运算符访问。
  • 如果只需要成员指针不需要字段引用,删掉辅助实现里传boost::pfr::get<Is>(...)的参数即可。

内容的提问来源于stack exchange,提问作者Nick Strupat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 16:09:23