Bind2nd与用户定义的类有关

时间:2013-07-21 20:30:46

标签: c++ 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>'
}

2 个答案:

答案 0 :(得分:2)

首先,您必须包含功能才能使用活页夹功能。

其次,您需要将operator()指定为const。

第三,为了获取类型特征信息,比如* 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;
}

修改

如果您可以访问C ++ 11感知编译器和stdlib,则可以轻松地将矢量填充代码重写为:

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功能。如果我是你,我会,如果你不被允许,那么(引用着名的Alexandrescu先生)“打电话给你的经纪人。”:))

顺便说一下。 Ryan(参见评论)是绝对正确的,当他提到时,即使是我最精心设计的std :: generate的东西;)也可以使用iota缩短编写:

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

std :: iota在 numeric 中定义。所以你也要把它包括在内。

希望有所帮助。

答案 1 :(得分:2)

这完成了Stefan的回答,他指出std::bind将const引用作为仿函数参数,因此operator ()必须是const。

现在,您的二元仿函数必须适应std::bind2ndbind2nd希望F输入first_argument_typesecond_argument_typeresult_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更通用,更灵活的解决方案,没有这些必需的typedef