Что не так с моим лямбда-выражением в Фениксе?

Я ожидаю, что следующий пример 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

Решение

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 унарная функция. Затем вы пытаетесь вызвать нулевую функцию с arg1, Boom.

Вот код, который выполняет и выполняет (во что я верю) ваше намерение:

#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 и феникс прицелы.

4

Другие решения

Мне не ясно, чего вы пытаетесь достичь, используя 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

Возможно, это может объяснить это лучше.

Феникс не магия; это прежде всего C ++. Следовательно, следует правила C ++.

phx::bind это функция, которая возвращает объект функции, объект с перегруженным operator() который вызывает функцию, которая была связана. Ваше первое заявление сохраняет этот объект в plus_1,

Учитывая все это, в любой момент у тебя есть выражение plus_1(...), это вызов функции. Это и есть; Вы говорите, что хотите позвонить перегруженным operator() функция на тип этого объекта, и что вы собираетесь передать некоторые значения этой функции.

Неважно, находится ли это выражение в середине [] или нет. phx::lambda не может заставить C ++ изменить свои правила. Это не может сделать plus_1(...) что-нибудь Другой чем немедленный вызов функции. Не может arg1 делать plus_1(...) не немедленный вызов функции.

1
По вопросам рекламы [email protected]