Я пытаюсь узнать, как использовать 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>'
}
Прежде всего, вы должны включить функциональная использовать функциональность связующего.
Во-вторых, вам нужно указать ваш оператор (), чтобы быть постоянным.
В-третьих, для получения информации о типах, например * 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 определяется в числовой. Таким образом, вы должны включить это также.
Надеюсь, это поможет.
Это завершает ответ Стефана, который указал, что 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