为容器中的每个对象调用带有一个参数(绑定)的成员函数

时间:2012-03-18 12:00:35

标签: c++ algorithm numeric mem-fun bind2nd

我有一个

using namespace std;
typedef vector<Coil*> CoilVec;
CoilVec Coils;

CoilCilCoilRectCoil的基类,分别是圆柱形线圈和矩形线圈。现在,我希望在calcField中指向的每个Coil上调用成员函数Coils。此成员函数在基类中纯粹是虚拟的,但已在派生类中实现,其声明如下所示:

virtual TVector3 calcField(const TVector3&);

TVector3是来自RooT库的3D矢量类。现在的想法是计算Coil中每个Coils的字段并将它们加在一起。由于calcField的参数(即计算字段的位置的向量)对于每个调用都是相同的,我想使用来自<algorithm>或{{1的STL算法标题做这样的事情(想象):

<numeric>

显然,既然我在这里问一个问题,这似乎不起作用。所以我的问题很简单:为什么这不起作用和/或你如何以正确的方式(在STL的限制范围内)做到这一点?

我在尝试编译上面时收到以下错误消息(我正在使用的文件名为Interface.cpp,它是第三方代码):

using namespace std;
typedef vector<Coil*>::const_iterator CoilIt;
const TVector3& P(1.,1.,1.); // Let's say we want to know the total field in (1,1,1)
TVector3 B; // Default initialization: (0,0,0)
CoilIt begin = Coils.begin();
CoilIt end = Coils.end();
B = accumulate(begin, end, B, bind2nd(mem_fun(&Coil::calcField), P));

4 个答案:

答案 0 :(得分:0)

传递给std::accumulate()的函数必须是二元函数,每次调用函数时都会给出两个参数(已经累加的值和向量的下一个元素)。

传递给std::accumulate()的绑定函数只需要一个参数Coil*。要与accumulate一起使用,必须使用两个参数(Vector3DCoil*)。

答案 1 :(得分:0)

bind2nd来电的结果是一个带Coli*的一元函数。 std::accumulate期望可以使用累加器和当前值调用二进制函数,即它需要一个带(TVector3, Coli*)的函数。

您尝试执行的操作似乎是将每个Coli*转换为TVector3,然后累积结果。

您可以使用明确的std::transform步骤来填充vector<TVector3>,然后使用std::accumulate,或者您可以编写一个单独的免费函数,其中(TVector3 t1, TVector3 t2, Coli* c)返回t2 + c->calcField(t1),然后在其上使用bind1st来获取二进制累加器函数。

如果你想在不编写单独的免费功能的情况下这样做,你需要boost::bind或C ++ 11。

答案 2 :(得分:0)

使用mem_funbind2nd和朋友编译代码可能不值得。我强烈建议写一个好的老式循环:

for (CoilIt it = coils.begin(); it != coils.end(); ++it)
{
    B += (**it).calcField(P);
}

答案 3 :(得分:0)

你想要的是嵌套绑定。那些难以置信的难度 已弃用的活页夹。以下是boost::bind的简化示例:

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#include <numeric>
#include <boost/bind.hpp>

struct A {
  double foo(double d) { return d; }
};

int main()
{
  std::vector<A> vs;
  double d = 0.0;
  d = std::accumulate(begin(vs), end(vs), d, 
                      boost::bind(std::plus<double>(), _1, 
                                  boost::bind(boost::mem_fn(&A::foo), _2, 0.0)));
  return 0;
}

我相信你的误解是你假设累积用途 operator+积累你传入的仿函数的结果 事实上,仿函数用于累积结果。这是基于 函数式编程中fold的一般概念。

您传入的仿函数必须为

形式
Ret func(const T1& a, const T2& b)

其中Ret必须可转换为T(init参数的类型), T1必须T可以隐式转换为T2 {{1}} 必须是将迭代器解引用到的结果 序列必须可以隐式转换为它。