Как создать лямбда-функцию для соответствия параметру boost :: function без использования C ++ 0x? - PullRequest
5 голосов
/ 08 июля 2011

Как мне создать лямбда-функцию, используя boost или stl, чтобы соответствовать параметру boost::function, ожидаемому F в третьем фрагменте кода в main?

#include <iostream>
#include <boost/function.hpp>

void F(int a, boost::function<bool(int)> f) {
    std::cout << "a = " << a << " f(a) = " << f(a) << std::endl;
}

bool G(int x) {
    return x == 0;
}

int main(int arg, char** argv) {
    // C++0x
    F(123, [](int i) { return i==0; } );

    // Using seperate function
    F(0, &G);

    // How can I do it in place without C++0x
    F(123, /* create a lambda here to match */);
}

Я не могу использовать C ++ 0x и хотел бы избежать создания нескольких отдельных функций. Я могу использовать что-то другое, что boost::function, если это поможет, моим приоритетом является создание лямбда лаконично.

Ответы [ 2 ]

7 голосов
/ 08 июля 2011
#include <functional>    // STL
#include <boost/lambda/lambda.hpp>   // Boost.Lambda
#include <boost/spirit/include/phoenix_core.hpp>     // Boost.Pheonix
#include <boost/spirit/include/phoenix_operator.hpp> // Boost.Pheonix also

...

// Use STL bind without lambdas
F(0, std::bind2nd(std::equal_to<int>(), 0));
F(123, std::bind2nd(std::equal_to<int>(), 0));

// Use Boost.Lambda (boost::lambda::_1 is the variable)
F(0, boost::lambda::_1 == 0);
F(123, boost::lambda::_1 == 0);

// Use Boost.Phoenix
F(0, boost::phoenix::arg_names::arg1 == 0);
F(123, boost::phoenix::arg_names::arg1 == 0);

Вы можете добавить немного using namespace для упрощения кода.

Boost.Lambda строго для определения функторов, встроенных в синтаксис, подобный C ++, тогда как Boost.Phoenix - это язык функционального программирования, построенный на основе C ++, злоупотребляющий (☺) его синтаксисом и возможностью вычислений во время компиляции.Boost.Phoenix намного мощнее Boost.Lambda, но для компиляции первого также требуется гораздо больше времени.

0 голосов
/ 08 июля 2011

Краткий ответ: нет.

C ++ 0x лямбды были изобретены, чтобы делать именно то, что вы хотите.На самом деле они не более чем способ сделать Increment в приведенном ниже примере анонимным / встроенным.Это единственный способ получить анонимную функцию в любом из стандартных C ++.

struct Increment {
    int & arg;
    Increment (int a) : arg (a) {}
    void operator () (int & i)
        {arg += i;}
};

void foo (const std :: vector <int> & buffer, int x)
{
    std :: for_each (
        buffer .begin (), buffer .end (),
        Increment (x)); // C++98

    std :: for_each (
        buffer .begin (), buffer .end (),
        [&x] (int & i) {x += i;}); // C++0x
}

Единственная волшебная вещь в лямбдах - это то, что их тип не может быть написан, нокомпилятор может связать внутренний скрытый тип с std::function (или даже с указателем на функцию C при некоторых обстоятельствах).

Я публикую приведенный выше код, потому что я думаю, что ваш вопрос может не означать, что вы думаете, что он делает. Лямбда определенно является C ++ 0x, но в этом примере Increment является замыканием .(Некоторые скажут, что оно становится закрытием, только если вы вернете его, и связанная переменная выйдет из контекста, в котором она была связана - это придирчиво, но это то, что, скажем, делает Javascript).или замыкания?

...