Можно ли изменить этот код, чтобы избежать использования лямбда-выражения C ++? - PullRequest
0 голосов
/ 20 июня 2011

У меня есть этот код, и я хотел бы знать, могу ли я изменить его, чтобы избежать использования лямбда-выражения:

#include <vector>
#include <algorithm>
#include <iterator>

class B
{
public:
    B( double b ):b_(b){}
    double b_;
};

class A
{
public:
    double error( const B& b ) const {return a_-b.b_;};
    double a_;
};

int main(int argc, char* argv[])
{
    std::vector< B > bs;
    std::vector< double > ds;

    A a;
    a.a_ = 10;
    bs.push_back( B(1) );
    bs.push_back( B(2) );
    bs.push_back( B(3) );
    std::transform( bs.begin(), bs.end(), 
                    std::back_inserter( ds ), 
                    [&a](const B& b){return a.error(b);} );

    return 0;
}

Я хотел бы сохранить std::transform, но безлямбда.

Ответы [ 4 ]

5 голосов
/ 20 июня 2011

Да.Просто сделайте это, как мы делали в C ++ 03 годами: с функциональным объектом.

Большинство (если не все) ссылки на std::transform (и подобные алгоритмы) будут иметь примеры этого.

4 голосов
/ 20 июня 2011

В этом случае эквивалентный функтор имеет вид:

struct CallError {
    A &a;
    CallError(A &a) : a(a) {}
    double operator()(const B &b) { return a.error(b); }
};

Затем:

std::transform( bs.begin(), bs.end(), 
                std::back_inserter( ds ),
                CallError(a));

Обратите внимание, что для захвата лямбда-выражения требуется соответствующий элемент данных функтора.Поэтому лямбды «захватывать все» немного сложнее, так как вам нужно выяснить, какие переменные действительно использует лямбда.Еще одна вещь, которую лямбда делает для вас, в этом случае, когда лямбда-тело состоит из одного оператора return, это то, что он автоматически определяет тип возвращаемого значения.

2 голосов
/ 20 июня 2011

Может содержать ошибки синтаксиса или опечатки

double fn(const A &a, const B &b) {
   return a.error(b);
}

....

using std::placeholders::_1;

std::transform( bs.begin(), bs.end(), 
                std::back_inserter( ds ), 
                boost::bind(fn, a, _1) );
1 голос
/ 20 июня 2011

Просто излагая ответ Томалака:

struct ErrorFunctor {
  double a;
  ErrorFunctor(double a) : a(a) { }
  inline double operator()(const B & b) const { return a - b.b_; }
};

// ... later on ...
std::transform(bs.begin(), bs.end(), std::back_inserter(ds), ErrorFunctor(10));

Доступ к работе функционального объекта осуществляется через operator().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...