0. Boost.Hana.members
members
是定义在namespace boost::hana
下的一个变量,拥有类型members_t
。
member_t
内重载了运算符<Object> operator(Object&&)
,接收特定类型的结构体,并返回hana::tuple<...Xn>
,利用该元组,可以访问结构体的每个成员。
且该结构体内必须含有且在BOOST_HANA_DEFINE_STRUCT
中的成员才能被members
的反射机制所利用。
例如:
struct A {
int b;
BOOST_HANA_DEFINE_STRUCT(A,
(int, a),
(double,d))
};
那么members
就可以反射到a和d,但是无法反射获取b。
1. 问题阐述
在使用hana::members
去反射访问结构体成员时,出现了如下情况
已知operator()
返回元组类型,因此,像这样访问元组元素是可行的:
auto element0 = boost::hana::at_c<0>(boost::hana::members(A{}));
同时我们注意到。hana::tuple
重载了operator[]
用以访问元组元素,但是当我们自然地写出这样的语句时:
auto mems = boost::hana::members(A{});
auto element0 = mems[0];
却无法编译通过,且报错信息如下:
error: static assertion failed due to requirement 'hana::IntegralConstant<int>::value': hana::at(xs, n) requires 'n' to be an IntegralConstant
2. 尝试解决
我们查看源码发现,在at_t::opeartor()
的定义中有着:
static_assert(hana::IntegralConstant<N>::value,
"hana::at(xs, n) requires 'n' to be an IntegralConstant");
到这里,我们需要再弄清楚hana::IntegralConstant<N>
是什么
再次查看源码:
namespace detail {
template <typename C, typename Tag = typename tag_of<C>::type>
struct integral_constant_dispatch
: hana::integral_constant<bool,
hana::IntegralConstant<Tag>::value
>
{ };
template <typename C>
struct integral_constant_dispatch<C, C>
: hana::integral_constant<bool, false>
{ };
}
template <typename C>
struct IntegralConstant
: detail::integral_constant_dispatch<C>
{ };
我们大致能够看出,如果integral_constant_dispatch
的C
和Tag
类型不同,那么integral_constant::value
就是true
,否则,就是false
。
再查看tag_of
的模板(这里不再放出)和其特化,我们发现,非特化情况Tag
与类型C
相等,或者&
、&&
、const
、volatile
和const volatile
类型没有type
的定义。但其对std::integral_constant
具有特化,使得Tag
与类型C
不相等。
于是我们可以这样传参:
boost::hana::members(A{})[std::integral_constant<int, 1>{}];
编译通过,解决问题。
当然,使用boost.hana.integral_constant
依然可以,因为其继承了std::integral
不过,在boost::hana
中已经定义了hana::integral_constant
类型的变量int_c
,我们可以直接使用int_c<N>
来传参。