c++ 可以使用Boost.pfr将类型的字段转换为成员指针吗?

zwghvu4y  于 11个月前  发布在  其他
关注(0)|答案(2)|浏览(121)

我知道Boost.pfr可以用来替换类型的字段,并作为T&访问它们,但由于T&不能转换为T A::*,我想知道库中是否有什么东西可以允许访问成员指针的字段。

#include <boost/pfr.hpp>

struct A {
    int number;
    string text;
};

int main() {
    boost::pfr::for_each_field(A{1,"foo"},
        [](auto A::* field) { // wish this or something similar were possible
            
        }
    );
}

字符串

vlurs2pr

vlurs2pr1#

PFR没有这个(还没有?),但如果你最近有足够的提升,描述可能是你想要的。
请注意,它不像PFR那样具有自动魔力,但它确实给予了在编译时使用的成员指针信息。
在他们的“通用打印示例”中,你可以看到成员描述符对象包含一个成员pointer,它是指向成员的类型:

using Md = describe_members<T, mod_any_access>; // for exposition

boost::mp11::mp_for_each<Md>([&](auto D){

    if( !first ) { os << ", "; } first = false;

    os << "." << D.name << " = " << t.*D.pointer;

});

字符串

vlju58qv

vlju58qv2#

你不能得到指向成员函数的指针。但是你可以在没有对象的情况下遍历字段。结果索引和类型可以以类似于成员指针的方式使用,即稍后提供对象。你可以在编译时使用boost::pfr::tuple_size<T>::value>{}获取元组大小,然后编译时使用逗号折叠(已经制作了元组大小的索引序列)来遍历类的字段。
这里是一个可能的方法的草图,它比我目前所需要的更一般,但希望能说明这一点。

template <typename T, size_t I>
struct PfrMemFunPtr
{
    using type = T;
    using value_type = boost::pfr::tuple_element_t<I, T>;
    static constexpr size_t idx = I;
};

template <typename T, typename F, size_t... I>
void apply_impl(F&& f, std::index_sequence<I...>)
{
    (f(PfrMemFunPtr<T, I>{}), ...);
}
template <typename T, typename F>
void apply(F&& f)
{
    apply_impl<T>(std::forward<F>(f),
                  std::make_index_sequence<boost::pfr::tuple_size<T>::value>{});
}

struct P
{
    int i1 = 1;
    std::string h = "hello";
    int i2 = 2;
    std::string_view w = "world";
};

// Create vector of type-erased functions, which output each field given ostream + object
std::vector<std::function<void(std::ostream&, const P&)>> vec;
apply<P>([&](auto pfr_mem_fun_ptr) {
    vec.push_back([&](std::ostream& os, const P& p) {
            os << boost::pfr::get<pfr_mem_fun_ptr.idx>(p) << '\n'; }); });

P p;
for(auto&& f : vec)
    f(std::cout, p);

字符串
输出

1
hello
2
world

相关问题