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>'
}

      

0


source to share


2 answers


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.

+2


source


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

+2


source







All Articles