【问题标题】:macro that defines entire derived class from one function and certain type specifiers?从一个函数和某些类型说明符定义整个派生类的宏?
【发布时间】:2018-04-23 09:26:21
【问题描述】:

我有一个名为 system 的类。系统采用一些对象管理器并以某种方式更改其中的所有对象。

例如,可能有一个系统在 imageManager 中绘制所有图像。

每个派生类的工作方式有点像这样(伪代码):

class someChildClass : public System{
private:
     someObjectManager &mang1; //these are used by the update method.
     someOtherObjectManager &mang2;//the update method changes these somehow
public:
     someChildClass(someObjectManager &mang1, someObjectManager &mang2)
     :mang1(mang1),mang2(mang2){
     }
     virtual void update(){
     //this is pure virtual in the System base class.
     //Do something with the managers here
     }
}

我想写所有东西,但更新方法是浪费时间和错误的来源。我想编写一个宏,基本上可以像这样创建一个这样的类:

QUICKSYSTEM(thisIsTheSystemName, someObjectManager, mang1, someOtherObjectManager, mang2, ... (infinite possible Managers. So a variadic macro?)){
//this is the update function
}
}//this is the end braked for the class declaration. Its ugly but I dont know how I could do the function differently? 

好吧,我在制作宏时遇到了一些问题。一切正常,直到我需要将可变参数拆分为名称和类型。我现在不知道这是否可能,因为我不能轻松地在参数中来回切换或对它们应用简单的步骤以确保每个 2nd 都是变量的名称。我可以忽略名称的可能性,只是让类型具有某种自动命名(manager1、manager2、manager3 或类似的东西)。

如果使用宏无法做到这一点,那么在构造函数和类声明部分避免错误并缩短一些时间的更好方法是什么?

【问题讨论】:

    标签: c++ variadic variadic-macros


    【解决方案1】:

    是的,宏真的,真的不是这样做的方法。 C++ 有模板,它遵循 C++ 语法并支持 C++ 表达式。相反,宏使用自己的预处理器语言,这几乎完全不了解 C++。

    您还想了解一下std::tuple。处理所有这些名字的经理将是相当棘手的。元组是标准的解决方案。 managers.get<0>managers.get<someObjectManager> 都可以。

    【讨论】:

    • 注意:我发誓我已经考虑过std::tuple,与您的回答无关,但在发布之前我午休了^^
    • @YSC:你可以从我们的回答中清楚地看到哪个国家的午休时间更长^^
    • 这是我最自豪的国家成就:D
    • @YSC 更详细,但他使用了很多我还不明白的东西。我已经成功地使用元组和一些基本的可变参数模板制作了自己的版本,没有额外的东西。
    【解决方案2】:

    可变参数模板是您需要的工具:

    #include <iostream>
    #include <tuple>
    #include <functional>
    
    struct System { void virtual update() = 0; };
    template<class... Managers>
    struct ManagedSystem : System
    {
        std::function<void(Managers&...)> _update;
        std::tuple<Managers&...>          _managers;
    
        template<class F>
        ManagedSystem(F update, Managers&... managers) : _update(update), _managers(managers...) {}
    
        void update() override { _update(std::get<Managers&>(_managers)...); }
    };
    
    int main()
    {
        int n = 0;
        double d = 3.14;
        auto reset = [](int& a, double& d) { a = 0; d = 0.0; };
        ManagedSystem<int, double> ms{reset, n, d};
        ms.update();
        std::cout << "n = " << n << ", d = " << d << "\n";
        // n = 0, d = 0
    }
    

    这个想法是定义一个模板类(ManagedSystem),将多个管理器类型作为模板参数。这个类继承自System并提供了一个构造函数:

    1. 一个更新函子,
    2. 以及对类型由类的模板参数定义的管理器的引用。

    上述管理器在std::tuple 内部注册,并且(带有一点parameter pack magic 馈送到更新函子。

    从那里,您可以通过提供更新函数和类型列表来定义从System 继承的类。这避免了使用丑陋和类型不安全的宏,而支持不那么丑但类型字符串模板;)

    【讨论】:

      猜你喜欢
      • 2019-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多