craay 方法是不直接使用成员。
创建一个聚合可变参数模板。创建数据成员模板。
数据成员模板采用标签结构。
覆盖data_member<tag,T>::operator^( tag )
以返回对 的引用T
。Mqybe 免费做同样的事情operator^( data_member< tag, T >*, tag )
现在您可以通过 获取会员this^tag()
,这看起来像是会员访问。如果你创建一个全局实例,tag
你甚至可以删除()
.
您还可以对数据成员进行编译时反射,因此您可以编写for_each_member
和编写所有序列化代码一次,并将其用于每个struct
.
访问控制和其他类别的data_member
可以在aggregate
模板中完成。
基于标签的数据构造可以使用复杂而精美的aggregate
构造函数来完成。
或者,您可以等待真正的反射出现在 C++ 中,可能在十年内。
或者,您可以将您的struct
变成一个tuple
包装器,并使用类似上述覆盖技巧的东西来开始this^tag
基于名称的访问。
如果我们有一个struct foo
容器int x, y
并且double d
我们想要这样做,我们可能会执行以下操作:
// boilerplate
template<typename C, std::size_t idx> struct Tag {};
template<typename C, std::size_t tag_idx>
auto operator^(C&& lhs, Tag<C, tag_idx> const&>)
-> decltype( std::get<tag_idx>( std::forward<C>(lhs) )
{ return std::get<tag_idx>( std::forward<C>(lhs); }
struct foo:std::tuple< int, int, double > {};
Tag< foo, 0 > x; // another annoying part: need to manually number them
Tag< foo, 1 > y; // we can avoid this via an aggregate trick, but
Tag< foo, 2 > d; // even that isn't all that pretty
int main() {
foo bar;
bar^x = 7;
bar^y = 3;
bar^d = 3.14;
}
一个(严重的)问题是,两个不同struct
的 s 中的两个成员变量共享相同的“命名空间”,如果它们具有相同的名称,则会发生冲突。