简体   繁体   English

我的Phoenix lambda表达式有什么问题?

[英]What is wrong with my Phoenix lambda expression?

I would expect the following example Boost Phoenix expression to compile. 我希望下面的示例Boost Phoenix表达式可以编译。

What am I missing? 我想念什么?

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;
}
auto plus_1 = phx::bind(&plus,1,arg1);

After this line, plus_1 is a function object that takes one int argument and adds one to it. 在此行之后, plus_1是一个函数对象,该对象接受一个int参数并将其添加一个参数。

phx::lambda[plus_1(arg1)](1);

Whoops. 哎呀 This isn't going to work because (as we said above) plus_1 is a function object that takes one int argument and adds one to it. 这是行不通的,因为(如上所述) plus_1是一个函数对象,它接受一个int参数并将其添加一个。 Here, you're trying to invoke it with arg1 . 在这里,您尝试使用arg1调用它。

It isn't obvious from your code what you expect it to do. 从您的代码中看不出您期望它做什么。 Can you clarify? 你能澄清一下吗?

====EDIT==== ====编辑====

I see you've edited the code in your question. 我们看到您已修改问题中的代码。 Your code is still wrong but for a different reason now. 您的代码仍然是错误的,但是现在是由于其他原因。 This: 这个:

phx::val(plus_1)(arg1)

... uses val to create a nullary function that returns the plus_1 unary function. ...使用val创建一个空函数,该函数返回plus_1一元函数。 You then try to invoke the nullary function with arg1 . 然后,您尝试使用arg1调用无效函数。 Boom. 繁荣。

Here is code that executes and does (what I believe) you intend: 这是执行和执行(我相信)您打算的代码:

#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;
}

The first bind takes the binary plus and turns it into a unary function with the first argument bound to 1 . 第一个bind采用二进制plus并将其转换为一元函数,且第一个参数绑定为1 The second bind creates a new unary function that is equivalent to the first , but it does so by safely wrapping the first function using lambda . 第二个bind创建了一个新的一元函数,该函数bind一个bind 等效 ,但是它是通过使用lambda安全地包装第一个函数来实现的。 Why is that necessary? 为什么有必要? Consider the code below, which is equivalent, but without the lambda : 考虑下面的代码,这是等效的,但没有lambda

// Oops, wrong:
int value = phx::bind(phx::bind(&plus, 1, arg1), arg1)(1);

Notice that arg1 appears twice. 注意arg1出现了两次。 All expressions get evaluated from the inside out. 从内到外对所有表达式求值。 First, we'll bind the inner arg1 to 1 , then evaluate the inner bind yielding 2 , which we then try to bind and invoke. 首先,我们将内部arg1绑定到1 ,然后评估内部bind产生2 ,然后尝试进行绑定和调用。 That's not going to work because 2 isn't callable. 那是行不通的,因为2是不可调用的。

The use of lambda creates a scope for the inner arg1 so it isn't eagerly substituted. 使用lambda会为内部arg1创建一个范围,因此不会急切地替换它。 But like I said, the use of the second bind , which forces the need for lambda , yields a function that is equivalent to the first. 但是就像我说的那样,使用第二个bind强制需要lambda ,它产生的功能与第一个相同。 So it's needlessly complicated. 因此,它不必要地复杂。 But maybe it helped you understand about bind , lambda and Phoenix scopes. 但是也许它可以帮助您了解bindlambda和Phoenix范围。

It's not clear to me what you're trying to accomplish by using lambda here, but if you just want to call plus_1 with 1 (resulting in 2 ), it's much simpler than your attempt: 我不清楚您要在此处使用lambda试图完成什么,但是如果您只想用1调用plus_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';
}

Online demo 在线演示

If this isn't what you're trying to accomplish, then you need to describe what you actually want. 如果这不是您要实现的目标,则需要描述您实际想要的目标。 :-] :-]

Perhaps this can explain it better. 也许这可以更好地解释它。

Phoenix is not magic ; 凤凰不是魔术 ; it is first and foremost C++. 它是最重要的C ++。 It therefore follows the rules of C++. 因此,它遵循C ++的规则

phx::bind is a function that returns a function object, an object which has an overloaded operator() that calls the function that was bound. phx::bind是一个返回函数对象的函数,该对象具有重载的operator() ,该operator()调用绑定的函数。 Your first statement stores this object into plus_1 . 您的第一条语句将该对象存储到plus_1

Given all of this, anytime you have the expression plus_1(...) , this is a function call . 鉴于这一切, 任何时候你有表达plus_1(...)这是一个函数调用 That's what it is; 就是这样; you are saying that you want to call the overloaded operator() function on the type of that object, and that you are going to pass some values to that function. 您是说要对该对象的类型调用重载的operator()函数,并且要向该函数传递一些值。

It doesn't matter whether that expression is in the middle of a [] or not. 该表达式是否位于[]中间并不重要。 phx::lambda cannot make C++ change its rules. phx::lambda无法使C ++更改其规则。 It can't make plus_1(...) anything other than an immediate function call. 它不能使plus_1(...)不是立即函数调用其他任何东西。 Nor can arg1 make plus_1(...) not an immediate function call. arg1也不能进行plus_1(...)不是立即函数调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM