Bind2nd problem with custom class
I'm trying to find out how to use bind2nd with custom classes, but I get an error that I can't figure out how to fix, despite my efforts to find other resources for help.
Help would be appreciated, thanks.
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>'
}
source to share
First of all, you must enable functionality to use the functionality of the binder.
Second, you need to specify that your operator () will be const.
Third, to get information about properties of a type, like * first_argument_type * etc., in your case it is better to inherit from 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;
}
Edit
If you have access to a compiler with C ++ 11 support and stdlib, your vector filling code can be easily rewritten to:
std::vector<int> bases(5);
int i = 0;
std::generate(bases.begin(), bases.end(), [&i]() { return ++i; });
Since C ++ 11 there is a new binder (moved from boost :: bind) std :: bind. It is much more flexible and you can try it if you like. For example:
using namespace std::placeholders;
std::transform(std::begin(bases), std::end(bases), std::begin(bases),
std::bind(F(), 2, _1));
(I just saw from the answer below that a.lasram mentioned new std :: bind. I don't know if you are allowed in your project or something else to use the new C ++ 11 instead of the old C ++ 03 functionality . If I were you, I would, if you were not allowed, then (to quote from the famous Mr. Alexandrescu) "Call your agent." :))
Btw. Ryan (see comments) is absolutely right when he mentions that even the most complicated std :: generate thing;) can be written in a shorter way with iota
:
std::iota(bases.begin(), bases.end(), 1);
std :: iota is defined numerically. Therefore, you must include this as well.
Hope it helps.
source to share
This completes Stefan's answer, who pointed out that it std::bind
takes a reference constant as a functor argument, and therefore operator ()
must be const.
Your binary functor should now be adapted to std::bind2nd
.
bind2nd
expects F
for a typedef first_argument_type
, second_argument_type
and 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 introduces a std::bind
more general and flexible solution that lacks these required typedefs
source to share