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

C++ 为容器中的每个对象调用具有一个参数(绑定)的成员函数,c++,algorithm,numeric,mem-fun,bind2nd,C++,Algorithm,Numeric,Mem Fun,Bind2nd,我有一个 using namespace std; typedef vector<Coil*> CoilVec; CoilVec Coils; TVector3是根库中的3D向量类。现在的想法是计算线圈中每个线圈的磁场,并将它们相加。由于calcField的参数即计算字段位置的向量对于每个调用都是相同的,因此我想使用or头中的STL算法来执行如下操作: using namespace std; typedef vector<Coil*>::const_iterator

我有一个

using namespace std;
typedef vector<Coil*> CoilVec;
CoilVec Coils;
TVector3是根库中的3D向量类。现在的想法是计算线圈中每个线圈的磁场,并将它们相加。由于calcField的参数即计算字段位置的向量对于每个调用都是相同的,因此我想使用or头中的STL算法来执行如下操作:

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));
显然,既然我是来问一个问题的,这似乎不起作用。所以我的问题很简单:为什么这不起作用和/或你将如何在STL的范围内以正确的方式进行

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

In file included from /usr/include/c++/4.5/numeric:62:0,
                from Interface.cpp:7: /usr/include/c++/4.5/bits/stl_numeric.h: In function ‘_Tp std::accumulate(_InputIterator, _InputIterator, _Tp, _BinaryOperation) [with _InputIterator = __gnu_cxx::__normal_iterator<Coil* const*, std::vector<Coil*> >, _Tp = TVector3, _BinaryOperation = std::binder2nd<std::mem_fun1_t<TVector3, Coil, const TVector3&> >]’:
Interface.cpp:289:72: instantiated from here
/usr/include/c++/4.5/bits/stl_numeric.h:150:2: error: no match for call to ‘(std::binder2nd<std::mem_fun1_t<TVector3, Coil, const TVector3&> >) (TVector3&, Coil* const&)’
/usr/include/c++/4.5/backward/binders.h:147:7: note: candidates are: typename _Operation::result_type std::binder2nd<_Operation>::operator()(const typename _Operation::first_argument_type&) const [with _Operation = std::mem_fun1_t<TVector3, Coil, const TVector3&>, typename _Operation::result_type = TVector3, typename _Operation::first_argument_type = Coil*]
/usr/include/c++/4.5/backward/binders.h:153:7: note:                  typename _Operation::result_type std::binder2nd<_Operation>::operator()(typename _Operation::first_argument_type&) const [with _Operation = std::mem_fun1_t<TVector3, Coil, const TVector3&>, typename _Operation::result_type = TVector3, typename _Operation::first_argument_type = Coil*]
传递给std::accumulate的函数必须是一个二进制函数,每次调用该函数都会得到两个参数,即已累积的值和向量的下一个元素

传递给std::accumulate的绑定函数只接受一个参数,即Coil*。要与accumulate一起使用,它必须采用两个参数Vector3D和Coil*

bind2nd调用的结果是一个采用Coli*的一元函数。accumulate需要一个可以用累加器和当前值调用的二进制函数,也就是说,它需要一个接受TVector3,Coli*的函数

看起来你要做的是将每个大肠杆菌*转化为TVector3,然后累积结果

您可以使用显式的std::transform步骤来填充向量,然后使用std::accumulate,或者您可以编写一个单独的自由函数,该函数接受TVector3 t1、TVector3 t2、Coli*c,返回t2+c->calcFieldt1,然后使用bind1st获得二进制累加器函数


如果您不想编写单独的免费函数,则需要boost::bind或C++11。

让您的代码与mem_fun、bind2nd和friends一起编译可能是不值得的。我强烈建议写一个好的老式循环:

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

您需要的是嵌套绑定。这些都很难处理 不推荐使用的活页夹。下面是boost::bind的简化示例:

其中Ret必须可转换为init参数的类型T, T1必须使T可以隐式地转换为it和T2 必须确保将迭代器解引用到
序列必须隐式转换为它。

当您在STL中要求某些内容时,不会给出这个答案,但您是否考虑过Boost库特别是Boost::bind?我在切换时遇到了同样的问题。听起来你想要的是每个,而不是累加。线圈是一种类型,而不是一个对象,所以线圈.begin没有意义。@chameco:我已经考虑过了,但在这种情况下我宁愿坚持使用STL。@Wouter不,你真的不应该。由于某种原因,bind1st和bind2nd已被弃用。你想要的对他们来说是不可能的。我必须学习一些boost的知识才能真正理解这一点。我们应该在星期二的C++课程中查看Boost库。希望这将有助于澄清问题。但正如我在评论我的问题时所说:我希望STL解决方案是可能的,至少目前是这样。@Wouter C++11有std::bind,它只是boost::bind的标准版本。上面的代码应该与它几乎100%兼容。如果你有一个最新的编译器,就用它吧。同样,您可能会在最近的编译器中使用lamdba来实现这一点。在我深入研究boost之前,这可能是我的临时解决方案。尽管如此,我还是希望避免for循环,即使它们看起来可以接受。这实际上是编译!我仍然需要运行一些测试来检查它是否符合我的要求,但我希望:
for (CoilIt it = coils.begin(); it != coils.end(); ++it)
{
    B += (**it).calcField(P);
}
#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;
}
Ret func(const T1& a, const T2& b)