考虑以下:
typedef struct {
int a;
int b;
int c;
int d;
} ABCD;
typedef std::vector<ABCD> VecABCD;
Run Code Online (Sandbox Code Playgroud)
假设我想在VecABCD类型的向量中添加每个'a'成员.简单!我只是循环遍历向量,并在我去的时候求和.
int CalcSumOfA(const VecABCD &vec)
{
int sumOfA = 0;
VecABCD::const_iterator it;
for(it=vec.begin();it!=vec.end();it++)
sumOfA += it->a;
return sumOfA;
}
Run Code Online (Sandbox Code Playgroud)
说我想用'b'做同样的事情?简单!我写....基本上是相同的功能,但只有微不足道的变化.与'c'和'd'相同.
那么,有没有更简洁,更少重复的方式来做到这一点?我想做点什么:
int sumOfA = SumOfMembers(myVec, a);
Run Code Online (Sandbox Code Playgroud)
但我无法想象我如何将这样的功能放在一起.理想情况下,它是一个模板,我可以使用任何类型结构的向量,而不是专门绑定到VecABCD.有人有主意吗?
Tod*_*ner 16
STL总结可以用来完成 std::accumulate
#include <functional>
accumulate(v.begin(), v.end(), 0, bind(plus<int>(), _1, bind(&ABCD::a, _2)))
Run Code Online (Sandbox Code Playgroud)
如果您希望这更通用,可以将tr1 :: function作为要绑定的成员:
int sum_over_vec(const vector<ABCD>& v, const tr1::function<int (const ABCD&)>& member)
{
return accumulate(v.begin(), v.end(),
0,
bind(plus<int>(),
_1,
bind(member, _2)));
};
// ...
int sum_a = sum_over_vec(vec, bind(&ABCD::a, _1));
Run Code Online (Sandbox Code Playgroud)
另一种方法是使用boost :: transform迭代器将逻辑放在迭代器中,而不是将逻辑放在仿函数中:
tr1::function<int (const ABCD&)> member(bind(&ABCD::a, _1));
accumulate(make_transform_iterator(v.begin(), member),
make_transform_iterator(v.end(), member),
0);
Run Code Online (Sandbox Code Playgroud)
编辑添加:C++ 11 lambda语法
对于C++ 11 lambdas来说,这变得更加清晰(虽然不幸的是不会更短):
accumulate(v.begin(), v.end(), 0,
[](int sum, const ABCD& curr) { return sum + curr.a });
Run Code Online (Sandbox Code Playgroud)
和
int sum_over_vec(const vector<ABCD>& v, const std::function<int (const ABCD&)>& member)
{
return accumulate(v.begin(), v.end(), 0,
[&](int sum, const ABCD& curr) { return sum + member(curr}); });
};
Run Code Online (Sandbox Code Playgroud)
用法:
// Use a conversion from member function ptr to std::function.
int sum_a = sum_over_vec(vec, &ABCD::a);
// Or using a custom lambda sum the squares.
int sum_a_squared = sum_over_vec(vec,
[](const ABCD& curr) { return curr.a * curr.a; });
Run Code Online (Sandbox Code Playgroud)
Ada*_*eld 11
另一种选择是使用指向成员的指针:
int CalcSumOf(const VecABCD & vec, int ABCD::*member)
{
int sum = 0;
for(VecABCD::const_iterator it = vec.begin(), end = vec.end(); it != end; ++it)
sum += (*it).*member;
return sum;
}
...
int sumA = CalcSumOf(myVec, &ABCD::a); // find sum of .a members
int sumB = CalcSumOf(myVec, &ABCD::b); // find sum of .b members
// etc.
Run Code Online (Sandbox Code Playgroud)