是否有任何内置的 C++ 机制能够自动生成代码来调用类的每个成员上的函数或运算符?
例如,如果我们有数百种类型需要使用一组特定的函数或运算符。在每一种类型中,每种类型都需要为其所有成员调用相同的函数或运算符(仅此而已)。
对于一些特定的示例,我们可以说类型具有函数Save()and Load(),或流运算符<<and >>。怎样才能在调用时自动执行++呢A.Save(s)?如果代码只是将执行相同地传递给所有成员,是否有任何方法可以自动化该过程?B.Save(s)C.Save(s)TYPE::Save(stream s)
这是自动生成的一些代码的示例(仅是函数Save())。编辑注意:此示例显示所有 3 个成员为同一类型,但该解决方案应该适用于任何类型组合的成员,只要它们都共享相关的函数/运算符
class TYPE
{
protected:
XTYPE A, B, C;
public:
void Save(stream s)
{
A.Save( s );
B.Save( s );
C.Save( s );
}
};
Run Code Online (Sandbox Code Playgroud)
我的一个旧引擎使用疯狂的循环宏来实现这一目标。它使得使用宏构建类型变得更加容易(当有数百个类使用它们时),并且生成的类并不难理解,但宏本身很混乱并且过于复杂。我希望有更多的东西......内置到语言中。
正如 P Kramer 提到的,您可能可以使用一些反思技巧。另一种选择是尝试减少必须编写的代码量。一个技巧是创建一个接受参数 pack的 lambda,并使用折叠表达式对包中的每个项目应用一些操作,如下所示:
void Save(stream s)
{
[&](auto&&... members) {
(members.Save(s), ...);
} (A, B, C);
}
Run Code Online (Sandbox Code Playgroud)
即使A,B和C具有不同的类型,只要它们都有一个Save()成员函数,上面的方法就可以工作。
您也可以使用常规模板函数而不是 lambda 来完成此操作,但上面是编写它的最短方法。它仍然要求您列出要应用该函数的所有成员变量的名称,您可以考虑将其放入宏中:
#define MEMBERS A, B, C
class TYPE
{
protected:
XTYPE MEMBERS;
public:
void Save(stream s)
{
[&](auto&&... members) {
(members.Save(s), ...);
} (MEMBERS);
}
};
Run Code Online (Sandbox Code Playgroud)
受 Vincent 答案的启发,您还可以添加一个返回成员变量std::tuple引用std::apply的函数,然后可以使用上面的 lambda 对其进行迭代:
class TYPE
{
protected:
XTYPE A, B, C;
auto Members()
{
return std::forward_as_tuple(A, B, C);
}
public:
void Save(stream s)
{
std::apply([&](auto&&... members) {
(members.Save(s), ...);
}, Members());
}
};
Run Code Online (Sandbox Code Playgroud)
灵活性稍差,但代码更紧凑的是创建一个成员函数,该函数将函数作为参数,并将该函数应用于所有成员:
class TYPE
{
protected:
XTYPE A, B, C;
void ApplyToMembers(auto&& func)
{
[&](auto&&... members) {
(func(members), ...);
} (A, B, C);
}
public:
void Save(stream s)
{
ApplyToMembers([&](auto&& member){ member.Save(s); });
}
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
208 次 |
| 最近记录: |