自动生成基于会员的操作?

Rob*_*ert 3 c++ class member

是否有任何内置的 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)

我的一个旧引擎使用疯狂的循环宏来实现这一目标。它使得使用宏构建类型变得更加容易(当有数百个类使用它们时),并且生成的类并不难理解,但宏本身很混乱并且过于复杂。我希望有更多的东西......内置到语言中。

G. *_*pen 5

正如 P Kramer 提到的,您可能可以使用一些反思技巧。另一种选择是尝试减少必须编写的代码量。一个技巧是创建一个接受参数 pack的 lambda,并使用折叠表达式对包中的每个项目应用一些操作,如下所示:

void Save(stream s)
{
    [&](auto&&... members) {
        (members.Save(s), ...);
    } (A, B, C);
}
Run Code Online (Sandbox Code Playgroud)

即使A,BC具有不同的类型,只要它们都有一个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)