C++之无聊小技巧三.1

上文讨论了一工厂和访问者,为了贯彻娱乐精神,我们接下来组合这两个机制,看能搞出什么花样?

struct WidgetVisitor {
  virtual Widget *createNut(Nut &nut) = 0;
  virtual Widget *createBolt(Bolt &bolt) = 0;
};
struct Bolt : Widget {
  void accept(WidgetVisitor &v) { v.createBolt(*this); }
};
struct Nut : Widget {
  void accept(WidgetVisitor &v) { v.createNut(*this); }
};
struct WidgetFactory : WidgetVisitor {
  Widget *createNut(Nut &nut) { return new Nut; }
  Widget *createBolt(Bolt &bolt) { return new Bolt; }
};

使用的时候是这样:

Nut nut;
Bolt bolt;
WidgetFactory wc;
Nut *pNut = bolt.accept(wc);
Bolt *pBolt = nut.accept(wc);

哈哈,是不是有一种想打人的冲动?这也正体现本文的关键字——无聊。

之前的博文,回调函数的形参声明皆使用std::function,例如:

void work(int flag, std::function<void(int)> callback){
  callback(flag);
}

std::function说白了就是个函数指针wrapper。这里语义上函数在运行时匹配参数(实际编译器会看情况)。如果我们希望尽可能内联函数,就改成模板:

template <typename F>
void work(int flag, const F &callback){
  callback(flag);
}

调用时传入lambda表达式:

work(20, [](auto i){
  cout << i << endl;
});

看起来是没有问题。不过安全起见,诊断一下callback的类型:

//void work(){ ...
static_assert(std::is_convertible<callback, 
              std::function<void(int)>>::value);

这其实是STL的传统写法…不过还是褒贬不一。

说到std::function就想起出师未捷身先死的std::bind,真可怜…

Leave a Reply

Your email address will not be published. Required fields are marked *