我希望以下示例Boost Phoenix表达式能够编译。
我错过了什么?
int plus(int a,int b)
{
return a+b;
}
void main(int argc,char** argc)
{
auto plus_1 = phx::bind(&plus,1,arg1);
auto value = phx::lambda[phx::val(plus_1)(arg1)]()(1);
std::cout << value << std::endl;
}
答案 0 :(得分:4)
auto plus_1 = phx::bind(&plus,1,arg1);
在此行之后,plus_1
是一个函数对象,它接受一个int
参数并向其添加一个。
phx::lambda[plus_1(arg1)](1);
糟糕。这是行不通的,因为(正如我们上面所说)plus_1
是一个函数对象,它接受一个int
参数并向其中添加一个参数。在这里,您尝试使用arg1
调用它。
从您的代码中可以看出您的期望是什么。你能说清楚吗?
<强> ==== EDIT ==== 强>
我看到你已经在你的问题中编辑了代码。您的代码仍然是错误的,但现在出于不同的原因。这样:
phx::val(plus_1)(arg1)
...使用val
创建一个返回plus_1
一元函数的nullary函数。然后尝试使用arg1
调用nullary函数。吊杆。
以下代码执行并执行(我相信)您打算:
#include <iostream>
#include <boost/phoenix/phoenix.hpp>
namespace phx = boost::phoenix;
using phx::arg_names::arg1;
int plus(int a,int b)
{
return a+b;
}
int main()
{
auto plus_1 = phx::bind(&plus, 1, arg1);
int value = phx::bind(phx::lambda[plus_1], arg1)(1);
std::cout << value << std::endl;
}
第一个bind
接受二进制plus
并将其转换为一元函数,第一个参数绑定到1
。第二个bind
创建了一个新的一元函数,它等同于第一个,但它是通过使用lambda
安全地包装第一个函数来实现的。为什么这有必要?考虑下面的代码,它是等效的,但没有lambda
:
// Oops, wrong:
int value = phx::bind(phx::bind(&plus, 1, arg1), arg1)(1);
请注意arg1
出现两次。所有表达式都由内而外进行评估。首先,我们将内部arg1
绑定到1
,然后评估内部bind
产生2
,然后我们尝试绑定和调用它们。这不起作用,因为2
不可调用。
使用lambda
会为内部arg1
创建一个范围,因此不会急切地替换它。但就像我说的那样,使用强制需要bind
的第二个lambda
会产生一个与第一个相同的函数。所以这是不必要的复杂。但也许这有助于您了解bind
,lambda
和凤凰范围。
答案 1 :(得分:2)
我不清楚您在此处使用lambda
想要实现的目标,但如果您只想使用plus_1
致电1
(导致2
),它比你的尝试简单得多:
#include <iostream>
#include <boost/phoenix.hpp>
int plus(int a, int b)
{
return a + b;
}
int main()
{
namespace phx = boost::phoenix;
auto plus_1 = phx::bind(plus, 1, phx::arg_names::arg1);
std::cout << plus_1(1) << '\n';
}
如果不是您要完成的任务,那么您需要描述您真正想要的内容。 : - ]
答案 2 :(得分:1)
也许这可以更好地解释它。
凤凰不是魔法;它首先是C ++。因此它遵循C ++的规则。
phx::bind
是一个函数,它返回一个函数对象,一个具有重载operator()
的对象,它调用绑定的函数。您的第一个语句将此对象存储到plus_1
。
鉴于所有这一切, 随时 您有表达式plus_1(...)
,这是一个函数调用。就是这样;你是说你要在该对象的类型上调用重载的operator()
函数,并且你要将一些值传递给该函数。
表达式是否在[]
的中间并不重要。 phx::lambda
无法使C ++改变其规则。它不能使plus_1(...)
任何其他而不是立即函数调用。 arg1
也不能使plus_1(...)
成为即时函数调用。