2013-04-06 6 views
4

Я пытаюсь использовать boost::phoenix для эмуляции ямбда-выражений C++ для более старого компилятора, которому не хватает поддержки C++ 11, и я не могу вызвать простую функцию изнутри лямбда-выражение.Вызов функции изнутри boost :: phoenix :: lambda

C++ 11 Версия:

[](unsigned a) { foo(a); }(12678u); // calls foo(12678u) 

My Phoenix Lambda код выглядит следующим образом:

#include <cstdint> 
#include <iostream> 
#include <boost/phoenix.hpp> 

namespace ph = boost::phoenix; 
using ph::local_names::_a; 
using ph::placeholders::arg1; 

void foo(uint32_t val) 
{ 
    std::cout << "\t" << __func__ << "(" << val << ") called...\n"; 
} 

int main() 
{ 
    auto myLambda = ph::lambda(_a = arg1) 
     [ 
      foo(_a) 
      //std::cout << ph::val("Called with: ") << _a << ph::val("\n") 
     ](567u); 

    myLambda(); 

    return 0; 
} 

Это производит следующее сообщение об ошибке компилятора:

lambda-ex.cpp: In function ‘int main()’: 
lambda-ex.cpp:18:19: error: cannot convert ‘const _a_type {aka const boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::phoenix::detail::local<boost::phoenix::local_names::_a_key> >, 0l> >}’ to ‘uint32_t {aka unsigned int}’ for argument ‘1’ to ‘void foo(uint32_t)’ lambda-ex.cpp:20:15: error: unable to deduce ‘auto’ from ‘<expression error>’ 

Как я вызывать функцию из выражения лямбда Phoenix?

Я надеюсь, чтобы иметь возможность использовать phoneix::lambdas таким же образом, что я использовал C++ 11 лямбды в прошлом, например:

auto lambda1 = [&](uint32_t arg) 
       { 
        func1("Some Stuff", arg); 
        func2("Some More Stuff", aValueFromLocalScope, arg); 
        func3("Some Stuff", anotherValueFromLocalScope, arg); 
       }; 

someFuncImpl(aParam, lambda1); 
+0

Используйте [bind] (http://liveworkspace.org/code/aHc9d$10). – Mankarse

+0

@Mankarse Это простой пример - я не хочу просто заменять лямбда 'boost :: phoenix :: bind (& foo, arg1)' - Я пытаюсь использовать 'phoneix :: lambda' для эмуляции C++ 11 lambdas , – mark

+0

Кажется, что мое предложение было плохо продумано. [здесь] (http://liveworkspace.org/code/aHc9d$14) - это обновленная версия, которая вводит локальную переменную и вызывает несколько функций. – Mankarse

ответ

6

ph::lambda является неправильным инструментом для этой работы (ph::lambda - это инструмент для создания вложенных лямбда-выражений внутри выражения phoenix). Феникс-выражения - это уже функции, поэтому все, что вам нужно сделать, это найти способ вызова функций с помощью выражений феникса (bind), найти способ выполнения нескольких операций в последовательности (operator) и найти способ введения локальных переменные (let). Вводя это все вместе, дает:

#include <cstdint> 
#include <iostream> 
#include <boost/phoenix.hpp> 

namespace ph = boost::phoenix; 
using ph::local_names::_a; 
using ph::placeholders::arg1; 

#define FOO(name) void name(uint32_t val) {\ 
    std::cout << "\t" << __func__ << "(" << val << ") called...\n";\ 
} 
FOO(foo) 
FOO(bar) 
FOO(baz) 

int main() 
{ 
    auto&& myLambda = ph::let(_a = arg1) 
     [ 
      ph::bind(foo, _a), 
      ph::bind(bar, _a), 
      ph::bind(baz, _a) 
     ]; 

    myLambda(342); 

    return 0; 
} 
4

Это не имеет значения, если ваш пример тривиален или нет. Для вызова функций, отличных от Phoenix, необходимо использовать phoenix::bind. Период.

Лямбда в стиле Феникса наиболее эффективно используется для простых выражений с операторской перегрузкой. Вызов произвольных функций будет выглядеть уродливым.

C++ 11 не добавлял лямбда как функцию языка, потому что это было весело. Они сделали это, потому что различные библиотечные решения были каким-то образом неадекватны. Вы нашли одно из недостатков Феникса.

Смежные вопросы