0

我有一个

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

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

virtual TVector3 calcField(const TVector3&);

TVector3来自 Root 库的 3D 矢量类。现在的想法是计算每个输入的字段Coil并将Coils它们加在一起。由于每次调用的参数calcField(即计算字段的位置的向量)都是相同的,我想使用<algorithm>or<numeric>标头中的 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*]
4

4 回答 4

0

让您的代码与mem_fun,bind2nd和朋友一起编译可能不值得麻烦。我强烈建议改写一个好的老式循环:

for (CoilIt it = coils.begin(); it != coils.end(); ++it)
{
    B += (**it).calcField(P);
}
于 2012-03-18T12:48:24.053 回答
0

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

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

于 2012-03-18T12:34:26.030 回答
0

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

似乎您要做的是将每个转换Coli*为 aTVector3然后累积结果。

您可以通过显式std::transform步骤填充 avector<TVector3>然后使用来执行此操作std::accumulate,或者您可以编写一个单独的自由函数,该函数接受(TVector3 t1, TVector3 t2, Coli* c)、返回t2 + c->calcField(t1),然后使用bind1st它来获取二进制累加器函数。

如果您想在不编写单独的自由函数的情况下执行此操作,则需要boost::bindC++11。

于 2012-03-18T12:38:34.553 回答
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 必须使得将迭代器解引用到序列中的结果必须可以隐式转换为它。

于 2012-03-18T12:59:42.203 回答