gpt4 book ai didi

c++ - 使用 boost::pfr 获取字段名称

转载 作者:行者123 更新时间:2023-12-05 01:25:28 30 4
gpt4 key购买 nike

您好,我正在使用 boost::pfr 进行基本反射,它工作正常,但问题是它只是打印或处理字段值,就像 boost::pfr::io 它打印结构的每个成员,但我如何将它打印为名称值对,与 for_each_field 相同的问题,仿函数只接受值,但不接受名称。如何获取字段名称?

struct S {
int n;
std::string name;
};
S o{1, "foo"};
std::cout << boost::pfr::io(o);
// Outputs: {1, "foo"}, how can I get n = 1, name = "foo"?

最佳答案

如果您认为调整一个结构体并不太麻烦(它不会改变您现有的定义,您甚至不需要将它放在公共(public) header 中):

BOOST_FUSION_ADAPT_STRUCT(S, n, name)

然后你可以炮制一个通用operator<<对于序列:

namespace BF = boost::fusion;

template <typename T,
typename Enable = std::enable_if_t<
// BF::traits::is_sequence<T>::type::value>
std::is_same_v<BF::struct_tag, typename BF::traits::tag_of<T>::type>>>
std::ostream& operator<<(std::ostream& os, T const& v)
{
bool first = true;
auto visitor = [&]<size_t I>() {
os << (std::exchange(first, false) ? "" : ", ")
<< BF::extension::struct_member_name<T, I>::call()
<< " = " << BF::at_c<I>(v);
};

// visit members
[&]<size_t... II>(std::index_sequence<II...>)
{
return ((visitor.template operator()<II>(), ...);
}
(std::make_index_sequence<BF::result_of::size<T>::type::value>{});
return os;
}

(Prior to c++20 this would require some explicit template types instead of the lambdas, perhaps making it more readable. I guess I'm lazy...)

这是一个现场演示: Live On Compiler Explorer

n = 1, name = foo

奖励:正确引用类似字符串的类型

Live On Compiler Explorer

#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/fusion/include/at_c.hpp>
#include <iostream>
#include <iomanip>

namespace MyLib {
struct S {
int n;
std::string name;
};

namespace BF = boost::fusion;

static auto inline pretty(std::string_view sv) { return std::quoted(sv); }

template <typename T,
typename Enable = std::enable_if_t<
not std::is_constructible_v<std::string_view, T const&>>>
static inline T const& pretty(T const& v)
{
return v;
}

template <typename T,
typename Enable = std::enable_if_t<
// BF::traits::is_sequence<T>::type::value>
std::is_same_v<BF::struct_tag, typename BF::traits::tag_of<T>::type>>>
std::ostream& operator<<(std::ostream& os, T const& v)
{
bool first = true;
auto visitor = [&]<size_t I>() {
os << (std::exchange(first, false) ? "" : ", ")
<< BF::extension::struct_member_name<T, I>::call()
<< " = " << pretty(BF::at_c<I>(v));
};

// visit members
[&]<size_t... II>(std::index_sequence<II...>)
{
return (visitor.template operator()<II>(), ...);
}
(std::make_index_sequence<BF::result_of::size<T>::type::value>{});
return os;
}
} // namespace MyLib

BOOST_FUSION_ADAPT_STRUCT(MyLib::S, n, name)

int main()
{
MyLib::S o{1, "foo"};
std::cout << o << "\n";
}

输出:

n = 1, name = "foo"

关于c++ - 使用 boost::pfr 获取字段名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70821619/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com