更自然的 boost::bind 替代方案?

Posted

技术标签:

【中文标题】更自然的 boost::bind 替代方案?【英文标题】:A more natural boost::bind alternative? 【发布时间】:2009-02-01 13:36:17 【问题描述】:

不要误会我的意思: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++ 中的绑定?你只是接受提升给你的东西吗?

【问题讨论】:

【参考方案1】:

您似乎想要以下内容:

隐式绑定到this 与存储绑定的函数调用关联的括号的替代方法。 自动识别 lambda 表达式中绑定了哪些参数。

第一个在今天的 C++ 中非常困难,因为 this 在很少的上下文中是隐式的,你当然不能将它隐式传递给函数。 IE。您无法使用库函数实现此目的,但您可以使用宏。不过,它会很丑。

第二部分要容易得多:

button.clicked.handler = bind(BetBar::placeBet, this, bet_id);

这只需要handler.operator=(boost::function<void(*)()> const&)

第三个又是困难的,因为您刚刚设计了另一种两阶段名称查找的情况。这对模板来说已经够难了。 boost 的 _1 技巧通过明确哪些参数应该稍后绑定来起作用。但是, _1 作为名称并不神奇。它基本上是一个返回 boost::arg 的免费函数。因此,通过 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)

【讨论】:

【参考方案2】:

我怀疑你能在 pre-0x C++ 上得到比这更好的东西。 Boost.Lambda 或 Phoenix 提供了它们自己的绑定机制,但对于这种情况,它真的不会变得更具可读性。

如果您能想到如何使用 boost::proto 在当前 C++ 中编写这样的 DSL(还有其他替代方案吗?),那么您可能会从 boost 中仅有的其他 proto-guys 获得更好的帮助邮件列表本身,因为这超出了我的想象。

对于同事:当他们专业地进行 C++ 编程时(阅读:他们为此获得报酬),他们要么了解它,要么他们应该做另一份工作。如果他们无法阅读如此简单的结构,他们可能会产生更大的维护负担,然后他们可以通过帮助实现新功能来弥补。

在这种情况下,提供与 Lua(或您喜欢的任何脚本语言)的良好绑定,并让它们以该语言执行业务逻辑。无论如何,这实际上是一个不错的解决方案。

【讨论】:

proto 看起来令人兴奋,我一定会深入了解它。谢谢!【参考方案3】:

顺便说一句,实际上一个好的 DSL 可能看起来像这样:

btn.clicked  |bet_id| placeBet bet_id 
animator.eachFrame  |newPos| buttons[bet_id].move newPos 

回答您的问题:对于您提供的简单示例,bind 工作正常。

【讨论】:

以上是关于更自然的 boost::bind 替代方案?的主要内容,如果未能解决你的问题,请参考以下文章

CoreGraphics 替代方案?

API 级别 19 或更低级别的 LocalDate 替代方案?

PHP 中更漂亮/信息更丰富的 Var_dump 替代方案? [关闭]

Jenkinsfile:Bitbucket REST API 的明文用户名:密码/PAT 是不是有更安全的替代方案?

还在用Jenkins?看看这些替代方案,是否更适合你!

我对这种重复的替代解决方案是不是正确?