Bind2nd проблема с пользовательским классом

Я пытаюсь узнать, как использовать bind2nd с пользовательскими классами, но получаю ошибку, которую не могу понять, как исправить, несмотря на мои попытки поиска помощи в других ресурсах.

Помощь будет оценена, спасибо.

main.cpp

#include <algorithm>
#include <vector>

class F
{
public:
int operator()(int a, int b)
{
return a * b;
}
};

int main(void)
{
std::vector<int> bases;

for(int i = 0; i < 5; ++i)
bases.push_back(i);

std::transform(bases.begin(), bases.end(), bases.begin(), std::bind2nd(F(), 2));
// Error C2664: '_OutIt std::transform<std::_Vector_iterator<_Myvec>,std::_Vector_iterator<_Myvec>,
// std::binder2nd<_Fn2>>(_InIt,_InIt,_OutIt,_Fn1)' : cannot convert parameter 4 from
// 'std::binder2nd<_Fn2>' to 'std::binder2nd<_Fn2>'
}

0

Решение

Прежде всего, вы должны включить функциональная использовать функциональность связующего.

Во-вторых, вам нужно указать ваш оператор (), чтобы быть постоянным.

В-третьих, для получения информации о типах, например * first_argument_type * и т. Д., В вашем случае лучше наследовать от std :: binary_function.

#include <algorithm>
#include <vector>
#include <functional>
#include <iterator>
#include <iostream>

struct F : public std::binary_function<int, int, int>
{
int operator()(int a, int b) const
{
return a * b;
}
};

int main(void)
{
std::vector<int> bases;

for(int i = 0; i < 5; ++i)
bases.push_back(i);

std::transform(bases.begin(), bases.end(), bases.begin(), std::bind2nd(F(), 2));

// print it to stdout
std::copy(bases.begin(), bases.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
}

редактировать

Если у вас есть доступ к компилятору и stdlib, поддерживающему C ++ 11, ваш код векторной заливки можно легко переписать в:

std::vector<int> bases(5);
int i = 0;

std::generate(bases.begin(), bases.end(), [&i]() { return ++i; });

В C ++ 11 появилась новая связка (перенесена из boost :: bind) в std :: bind. Это гораздо более гибко, и вы можете попробовать, если хотите. Такие как:

using namespace std::placeholders;
std::transform(std::begin(bases), std::end(bases), std::begin(bases),
std::bind(F(), 2, _1));

(Я только что видел из ответа ниже, что a.lasram упомянул новый std :: bind. Я не знаю, разрешено ли в вашем проекте или что-то еще использовать новый C ++ 11 вместо старая функциональность C ++ 03. Если бы я был тобой, я бы, если бы тебе не позволили, ну тогда (по словам известного мистера Александреску) «Позвони своему агенту». :))

Btw. Райан (см. Комментарии) абсолютно прав, когда он упоминает, что даже моя самая сложная вещь std :: generate;) может быть написана короче, используя iota:

std::iota(bases.begin(), bases.end(), 1);

std :: iota определяется в числовой. Таким образом, вы должны включить это также.

Надеюсь, это поможет.

2

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

Это завершает ответ Стефана, который указал, что std::bind принимает константную ссылку в качестве аргумента функтора и, следовательно, operator () должен быть постоянным

Теперь ваш двоичный функтор должен быть адаптирован к std::bind2nd,
bind2nd надеется F чтобы определить first_argument_type, second_argument_type а также result_type,

class F
{
public:
typedef int first_argument_type;
typedef int second_argument_type;
typedef int result_type;

int operator()(int a, int b) const
{
return a * b;
}
};

C ++ 11 вводит std::bind более универсальное и гибкое решение, которое не имеет требуемых typedefs

2