不要误会我的意思:Boost的bind()
很棒。
但我不喜欢用它来编写和阅读代码,而且我已经放弃希望我的同事能够理解/使用它。
我最终得到这样的代码:
btn.clicked.connect(bind(&BetBar::placeBet, this, bet_id));
animator.eachFrame.connect(bind(&Widget::move, buttons[bet_id]));
虽然合乎逻辑,但与我称之为好的代码相差甚远。
为了演示...在C ++ 1x中我们将拥有:
btn.clicked.connect([&](int bet_id){ placeBet(bet_id); })
animator.eachFrame.connect([&](Point newPos) { buttons[bet_id].move(newPos) })
好的DSL看起来有点像这样:
on(btn.clicked) placeBet(bet_id);
on(animator.eachFrame) buttons[bet_id].move(eachFrame::newPos);
你如何应对C ++中的绑定?你是否只是生活在提升给你的东西?
答案 0 :(得分:3)
您似乎想要以下内容:
this
今天C ++中的第一个非常难,因为this
隐含在很少的上下文中,你当然不能隐式地将它传递给函数。即你无法用库函数实现这一点,但你可以使用宏。不过,这将是丑陋的。
第二部分要容易得多:
button.clicked.handler = bind(BetBar::placeBet, this, bet_id);
这只需要handler.operator=(boost::function<void(*)()> const&)
第三个很难,因为你刚刚设计了另一个两阶段名称查找案例。这对模板来说已经够难了。 boost的_1技巧通过明确哪些参数应该在以后绑定来起作用。但是,_1作为名称并不神奇。它基本上是一个返回boost :: arg&lt; 1&gt;的自由函数。因此,通过animator.eachFrame.newPos的合适定义,可以使以下内容相同:
animator.eachFrame.handler = bind(&Widget::move, buttons[bet_id], _1)
animator.eachFrame.handler = bind(&Widget::move, buttons[bet_id], animator.eachFrame.newPos)
答案 1 :(得分:2)
我怀疑你在0 C ++之前可以做得更好。 Boost.Lambda或Phoenix提供了他们自己的绑定机制,但对于这种情况,它实际上不会更具可读性。
如果你能想到如何使用boost :: proto在当前的C ++中编程这样的DSL(还有其他选择吗?),那么你可能会得到更好的帮助邮件列表本身,因为这将超出我的想象。
对于同事们:当他们专业地编写C ++编程时(阅读:他们得到了报酬),他们要么弄清楚,要么他们应该做另一份工作。如果他们无法阅读这些简单的结构,他们可能会产生更大的维护负担,然后他们可以帮助实现新功能。
在这种情况下,提供与Lua(或您喜欢的任何脚本语言)的良好绑定,并使它们使用该语言执行业务逻辑。无论如何,这实际上是一个不太糟糕的解决方案。
答案 2 :(得分:0)
作为旁注,实际上一个好的DSL看起来有点像这样:
btn.clicked { |bet_id| placeBet bet_id }
animator.eachFrame { |newPos| buttons[bet_id].move newPos }
回答你的问题:对于简单的例子,你提供了一个简单的bind
就可以了。