如何使用带有参数/修改的 std::foreach
Posted
技术标签:
【中文标题】如何使用带有参数/修改的 std::foreach【英文标题】:How to use std::foreach with parameters/modification 【发布时间】:2009-01-24 18:53:23 【问题描述】:我发现自己在写作
for(int i=0;i<myvec.size();i++)
myvec[i]->DoWhatever(param);
很多,我想将其压缩成foreach
语句,但我不确定如何在不冗长的情况下将param
放入其中。我也有类似的东西
for(int i=0;i<myvec.size();i++)
if(myvec[i]->IsOK())
myvec[i]->DoWhatever(param);
我也想重写那个人。有什么想法吗?
哦,还有,由于种种原因,我不想用boost。
【问题讨论】:
【参考方案1】:#include <vector>
#include <algorithm>
#include <functional>
class X
public:
void doWhat(int x)
bool IsOK() const return true;
;
class CallWhatIfOk
public:
CallWhatIfOk(int p): param(p)
void operator()(X& x) const
if (x.IsOK()) x.doWhat(param);
private:
int param;
;
int main()
std::vector<X> myVec;
std::for_each( myVec.begin(),
myVec.end(),
std::bind2nd(std::mem_fun_ref(&X::doWhat),4)
);
std::for_each( myVec.begin(),
myVec.end(),
CallWhatIfOk(4)
);
【讨论】:
【参考方案2】:哦,还有,由于种种原因,我不想用boost。
有效的决定,但很可能是错误的决定。将 Boost 视为 STL 的扩展。 C++ 是一种库驱动的语言。如果不考虑到这一点,你的代码会质量较差。
虽然可以在此处使用std::for_each
,但在 C++0x 之前 C++ 中没有 lambda 表达式使得这变得乏味。我提倡使用Boost.ForEach!它使这变得更容易:
foreach (yourtype x, yourvec)
if (x.IsOK())
x.Whatever();
【讨论】:
唉,是否使用 boost 不是我的决定。 可能想说你不能使用 boost。说你不想想要只是在要求一个论点......;)【参考方案3】:我首选的解决方案通常是编写一个仿函数来做我需要的事情:
struct doWhatever
doWhatever(const Param& p) p(p)
void operator(MyVec v&, Param p)
v.DoWhatever(param);
private:
Param p;
;
然后循环:
std::for_each(myvec.begin(), myvec.end(), doWhatever(param));
根据您有多少变体,这可能有点过于冗长。 不过,有很多选项可以内联。 boost::lambda 可以让你在调用点构造你需要的函数。 boost::bind(或标准库绑定函数)可以让您将参数 param 绑定到函数,因此您无需每次都将其作为参数提供。
boost::lambda 可能是最简洁灵活的方法。我通常使用普通函子方法,因为语法更容易记住。 ;)
【讨论】:
这是我所拥有的(并希望避免):) 嗯,没有提升(哎哟),我不认为你可以做的更短。在某些情况下, std::bind_* 东西可能会对您有所帮助,但没有任何灵丹妙药。 (至少在 c++0x 之前加上 lambda 表达式)【参考方案4】:当我们有支持 C++0x lambda 表达式的编译器时,这将变得简单且微创:
std::for_each(myvec.begin(),myvec.end(),[&](X& item)
item->DoWhatever(param);
);
第二个例子可能是这样的:
std::for_each(myvec.begin(),myvec.end(),[&](X& item)
if(item->IsOK())
myvec[i]->DoWhatever(param);
);
【讨论】:
太可惜了,它不适用于 g++ :(。我希望在某些时候我能够使用这些结构......【参考方案5】:#include <vector>
#include <algorithm>
#include <boost/bind.hpp>
#include <boost/lambda/if.hpp>
#include <boost/lambda/bind.hpp>
struct A
bool IsOK () return true;
void DoWhatever (int param)
;
struct B
bool IsOk (A * a) return true;
void DoWhatever (A * a, int param)
;
typedef std::vector<A *> Myvec;
void main()
Myvec myvec;
int param = 1;
B b;
// first challenge using boost::bind (fnct in the same class)
std::for_each (myvec.begin(), myvec.end(),
boost::bind (&A::DoWhatever, _1, param));
// first challenge using boost::bind (fnct in an external class)
std::for_each (myvec.begin(), myvec.end(),
boost::bind (&B::DoWhatever, &b, _1, param));
// second challange using boost::lambda (fnct in the same class)
std::for_each (myvec.begin(), myvec.end(),
boost::lambda::if_then(
boost::lambda::bind (&A::IsOK, boost::lambda::_1),
boost::lambda::bind (&A::DoWhatever, boost::lambda::_1, param)
)
);
// second challange using boost::lambda (fnct in an external class)
std::for_each (myvec.begin(), myvec.end(),
boost::lambda::if_then(
boost::lambda::bind (&B::IsOK, &b, boost::lambda::_1),
boost::lambda::bind (&B::DoWhatever, &b, boost::lambda::_1, param)
)
);
您可以使用命名空间来简化它...
【讨论】:
【参考方案6】:如果您使用的是 GCC,您可以定义如下内容:
#define foreach(element, array) \
for(typeof((array).begin()) element = (array).begin(), __end_##element = (array).end();\
element != __end_##element;\
++element)
然后像这样使用它:
foreach(element, array)
element->DoSomething(); //or (*element)->DoSomething() if type is already a pointer
我在自定义数组上使用它,但它也适用于 std::vector。
【讨论】:
以上是关于如何使用带有参数/修改的 std::foreach的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 JNI 从 JAVA 调用带有 C++ 参数的函数?
oracle中怎么执行带有输出参数的存储过程,在程序中我知道怎么调用,