模板化的回调

时间:2015-10-07 13:38:45

标签: c++ templates

标语可能不是很具描述性,但我无法想出更好的标语。但是,我希望能够解释这个问题。

我有一个框架,可以松散地映射到以下演示代码:

struct OpaqueStruct {
// OpaqueStruct allows introspection of it's members
// using templatized inrospect()
class OpaqueStruct {
  int i;
  double d;
  void* p;
public:
  template <class T> void introspect(T visitor) {
    visitor(i);
    visitor(d);
    visitor(p);
  }
};

template <class T> struct FunkyCaller {
  FunkyCaller(T* obj, int arg1, int arg2);
  template <class A> void operator() (A a) {
    obj->funky_impl(a, arg1, arg2);
  }
private:
  T* obj;
  int arg1;
  int arg2;
};

template <class T> struct FunkyCaller2 {
  // similar to FunkyCaller, but calls 
  // this->funky2_impl(arg);
};

// Benemoth is full of logic, code, data and lines
class Benemoth {
  OpaqueStruct opaque_data;
  void funky(int arg1, double arg2) {
    // Need to do something funky, taking args and opaque struct
    // as input
    opaque_data.introspect(FunkyCaller<Benemoth>(this, arg1, arg2));
  }

  void funky2(const char* arg) {
    // Need to do something funky, taking args and opaque struct
    // as input
    // opaque_data.introspect(FunkyCaller2<Benemoth>(this, arg));
  }
public:
  template <class ARG>
  void funky_impl(ARG a, int arg1, int arg2);

};

有很多代码,但我希望这个想法是可见的 - Benemoth中有不同的功能,需要以不同的方式处理opaque_data。我现在所拥有的设置,以及我在这里展示的设置,都有效。但是,我不喜欢它,因为每次我需要实现一个新函数来执行OpaqueData的新功能时,我需要为它创建一个“调用者”类。这使代码维护变得困难,因为代码受到那些“呼叫者”的污染。任何人都需要进行逆向工程,必须从funky()导航到FunkyCaller()funky_impl()。不太好。

我已经考虑过了什么?

  • C ++ 14模板lambda。工作正常,我的funky()看起来像opaque_data.introspect([this, arg1, arg2](auto datum) { this->funky_impl(datum, arg1, arg2); });。不幸的是,我们的项目尚未准备好使用C ++ 14
  • C ++ 11 lambdas,各种std::bind s。无法使它工作,因为它们都需要指定参数类型 - lambdas要求你指定参数类型,通过想要指向成员的指针来绑定
  • 宏。似乎不可能,即使它可能会比我目前的代码更不可读

有没有人看到任何减少代码混乱的方法?我没有,但可能我错过了什么?

0 个答案:

没有答案