静态循环访问C++结构的所有成员
Statically iterate over all members of a C++ struct
有没有办法静态迭代C++结构的所有成员?
假设我们有许多预定义的结构
,如下所示:struct Foo {
int field1;
double field2;
char field3;
...
int field9;
};
struct Bar {
double field14;
char field15;
int field16;
bool field17;
...
double field23;
};
我们想要一个模板函数
template<typename T>
void Iterate(T object);
以便Iterate
可以对类型 T
的所有成员Add
运行模板函数。例如,Iterate<Foo>
和Iterate<Bar>
将成为
void Iterate<Foo>(Foo object) {
Add<int>(object.field1);
Add<double>(object.field2);
Add<char>(object.field3);
...
Add<int>(object.field9);
}
void Iterate<Bar>(Bar object) {
Add<double>(object.field14);
Add<char>(object.field15);
Add<int>(object.field16);
Add<bool>(object.field17);
...
Add<double>(object.field23);
}
这可以通过编写另一个程序来完成,该程序解析struct
定义并生成cpp
文件,但这太麻烦了,需要额外的编译和执行。
编辑:结构可能有许多字段,并且它们是预定义的,因此无法更改为其他类型的字段。这也是在编译时,所以它与在运行时执行的"反射"关系不大,而与"模板编程"或"元编程"关系更大。我们在编译时<type_traits>
类型检查,但这似乎还不够。
没有明确的标准方法来做这样的事情,但你可以看看非标准的方法。例如,您可以使用 boost::fusion
.
BOOST_FUSION_ADAPT_STRUCT(
Foo,
(int, field1)
(double, field2)
(char, field3)
);
适应结构之后,您可以使用 Foo
类型的对象作为融合序列,可以按成员迭代。小活的例子
我看不到任何方法可以在不保留编译时信息以将索引映射到类型的情况下使用普通结构来做到这一点 - 此时您创建另一个 std::tuple 类。 让我们试一试:
#include <iostream>
#include <tuple>
#include <typeinfo>
template <size_t Cur, size_t Last, class TupleType, template <typename> class Func>
struct Iterate_Helper
{
void operator()(TupleType& tuple)
{
typedef typename std::tuple_element<Cur, TupleType>::type elem_type;
Func<elem_type>()(std::get<Cur>(tuple));
Iterate_Helper<Cur+1, Last, TupleType, Func>()(tuple);
}
};
template <size_t Cur, class TupleType, template <typename> class Func>
struct Iterate_Helper<Cur, Cur, TupleType, Func>
{
void operator()(TupleType& tuple)
{
typedef typename std::tuple_element<Cur, TupleType>::type elem_type;
Func<elem_type>()(std::get<Cur>(tuple));
}
};
template <template <typename> class Func, class TupleType>
void iterate(TupleType& tuple)
{
Iterate_Helper<0, std::tuple_size<TupleType>::value-1, TupleType, Func>()(tuple);
}
template <typename T>
struct Add1
{
void operator()(T& t)
{
t += 1;
}
};
template <typename T>
struct Print
{
void operator()(T& t)
{
std::cout << (int)t << std::endl;
}
};
int main() {
typedef std::tuple<int, double, char, /* ... */ int> Foo;
Foo test(1, 2.0, 3, 4);
iterate<Add1>(test);
iterate<Print>(test);
return 0;
}
这是我的头顶,但我希望它能给你一些见解。
是的,Boost.Fusion和扩展机制很好地支持了这一点。
你可以在这里找到一个for_each_member实现: https://github.com/cpp-pre/json/blob/master/pre/fusion/for_each_member.hpp
我使用它来生成 JSON 并从 json 读取结构,如我在此处的其他回复中所述:https://stackoverflow.com/a/28580824/271781
相关文章:
- 如何在C++中定义静态成员结构
- 使用模板化类的成员结构
- 初始化固定的 C 数组成员结构
- 指向成员结构的指针如何工作
- 如何将此“指针从外部类传递到成员结构
- 导致IAR ARM中出现错误的成员结构位字段元素的Initializer列表初始化
- 映射文件中成员结构的地址
- Visual C++ 模板类成员结构初始化语法糖
- C :初始化成员结构的静态字段的正确方法
- 如何在C 类的初始化器列表中使用未命名结构初始化成员结构
- 从成员结构的成员函数中访问类的成员?
- 模板化类的成员函数无法返回指向成员结构的指针?
- 重载非类型模板结构的成员结构的复制赋值运算符
- 灵气属性传播问题与单成员结构.
- 将具有 int* 成员C++结构编接到 C#
- 复杂的班级成员结构
- 将向量成员(结构)传递给函数
- 成员结构的前向声明
- 重载运算符<<用于模板结构中定义的成员结构
- 返回带有模板化类的类成员结构