c++ - 替代模板参数的转换构造函数

标签 c++ implicit-conversion crtp

我在 C++ 应用程序中使用 GLFW 进行窗口和输入管理。为了将成员函数用作关键事件的回调,我按照答案 here 中的建议使用了单例。 .

但是,我需要实现不同的输入处理程序。我的方法是使用 Singleton 作为实际输入处理程序 (controller_) 的包装器以允许多态性。但是,对于要实例化的 Singleton,基类不能是抽象的。解决方案涉及使用 CRTP为了能够从基类的实现中调用特定的输入处理方法。

  template <class T>
  class Controller : public BC{ //BC is just for using this class as a template parameter itself
    public:
    Controller(){}                    
    Controller(Controller &controller){
      controller_ = &controller;
    }

    static Controller& getInstance(Controller *controller){
      static Controller instance(*controller);
      return instance;
    }   

    //This is the key move, where the concrete implementation is invoked.
    static void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods){
      Controller *aux;
      (static_cast<T>(getInstance(aux))).keyCallbackImpl(window, key, scancode, action, mods); 
    }

    //Stub to be overridden by the concrete input handler        
    virtual void keyCallbackImpl(GLFWwindow* window, int key, int scancode, int action, int mods){}

    //This is the wrapped input handler
    Controller *controller_;   

  };

这很好用。但是,派生类有问题。为了能够执行转换,我必须定义一个转换构造函数。

SMController(Controller<SMController> &c){
  controller_ = c.controller_;
  std::cout << "Constructor" << std::endl;
}

这很不方便,原因有二:

  • 从 Controller 派生的用户必须显式定义此构造函数
  • 每次按下一个键都构建一个新的包装器似乎代价高昂

是否有使用此设计的替代方案?

编辑: 我最终接受了 T.C. 的提议,尽管略有不同。由于我需要子类具有它们自己的一组参数,因此能够在构造函数中提供它们是理想的。初始化单例的单独调用很容易出错,因为它可能是用错误的模板参数完成的,或者只是被遗忘了。

为了在一次调用中启用带有参数的专用对象及其对应的单例的实例化,我继续使用 CRTP,并将此构造函数添加到基类:

Controller<T>(){
  T::getInstance((T*)this);
}

现在,只需一个电话,我就能得到我需要的一切:

std::shared_ptr<BaseController> c(new SMController(params_, window_));

最佳答案

实际上,我真的不明白在这里使用 CRTP 有什么意义。直接存储指向模板参数的指针有什么问题?

template <class T>
class Controller : public BC { 
public:
  static Controller& getInstance(T * target = nullptr){
    static Controller instance(target);
    return instance;
  }   

  static void keyCallback(GLFWwindow* window, int key, int scancode,
                          int action, int mods){
    getInstance().target_->keyCallbackImpl(window, key, scancode, action, mods); 
  }
private:              
  Controller(T* target) : target_(target) { }   
  //This is the wrapped input handler
  T* target_;
};

关于c++ - 替代模板参数的转换构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25575057/

相关文章:

C++ 奇怪的重复模板模式,语法错误

c++ - 指向存储在结构中的数组的指针在哪里?

java - jsf - 字符串无法解析为数字

c++ - 访问内存以内联遍历数组

c++ - 当我在 on_read 上看到错误时,我应该清理 bread::flat_buffer 吗?

c++ - 为什么隐式转换对于非原始类型不模棱两可?

C++ 获取 std::variant 当前帮助的类型的 std::typeindex

c++ - 如何将奇怪的重复模板模式用于桥接模式?

c++ - 在不同进程上运行 Boost 单元测试

c++ - text_multifile_backend 如何为文件名设置动态日期