我发现自己正在写作
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。
答案 0 :(得分:15)
#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)
);
}
答案 1 :(得分:6)
哦,还有,由于各种原因,我不想使用boost。
有效决定,但很可能是错误的决定。将Boost视为STL的扩展。 C ++是一种库驱动的语言。如果你不考虑这一点,你的代码将在质量上低劣。
虽然这里可以使用std::for_each
,但是在C ++ 0x之前缺少C ++中的lambda表达式会使这很乏味。我主张使用Boost.ForEach!它使更多更容易:
foreach (yourtype x, yourvec)
if (x.IsOK())
x.Whatever();
答案 2 :(得分:4)
我首选的解决方案通常是编写一个仿函数来完成我需要的工作:
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可能是最简洁灵活的方法。我通常使用简单的仿函数方法,因为语法更容易记住。 ;)
答案 3 :(得分:3)
当我们有支持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);
});
答案 4 :(得分:3)
#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)
)
);
}
您可以使用命名空间来简化它......
答案 5 :(得分:0)
如果您使用的是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。