【发布时间】:2012-03-19 10:52:21
【问题描述】:
我有一个带有访问器成员函数的类,我想调用它并将结果应用到使用 std::for_each 的仿函数。我在下面有一个使用 for 循环和 for_each 的工作版本,但 for_each 版本既神秘又麻烦。考虑到我可以使用 boost 而不是 C++11,有没有办法可以使 for_each 版本更简洁?
#if 0
// for loop version:
for(value_vector_type::iterator it = values.begin(); it!=values.end(); it++){
avg(it->getValue()); // I want to put this in a for_each loop
}
#else
// bind version:
std::for_each(values.begin(), values.end(), // iterate over all values
boost::bind(
boost::mem_fn(&average_type::operator()), // attach the averaging functor to the output of the getvalue call
&avg,
boost::bind(
boost::mem_fn(&value_wrapper_type::getValue), // bind the getValue call to each element in values
_1
)
)
);
#endif
这是完整的工作实现:
#include <vector>
#include <algorithm>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/bind/mem_fn.hpp>
// A value wrapper
template<typename T>
struct Value {
Value(){}
Value(const T& value, bool valid = true):m_value(value),m_valid(valid){}
T getValue(){ return m_value; }
bool getValid(){ return m_valid; }
void setValue(const T& value){ m_value = value; }
void setValid(const T& valid){ m_valid = valid; }
private:
T m_value;
bool m_valid;
};
// Class that calculates the average piecewise
template<typename T>
struct Average {
private:
T m_numPoints;
T m_ChannelSum;
public:
Average() : m_numPoints(0), m_ChannelSum(0.0){}
void operator()(T value){
m_numPoints++;
m_ChannelSum+=value;
}
double getAverage(){ return m_ChannelSum/m_numPoints; }
T getCount(){ return m_numPoints; }
T getSum(){ return m_ChannelSum; }
};
// Run the average computation on several values
int main(int argc, char** argv){
typedef int value_type;
typedef Value<value_type> value_wrapper_type;
typedef std::vector<value_wrapper_type> value_vector_type;
value_vector_type values;
values.push_back(value_wrapper_type(5));
values.push_back(value_wrapper_type(7));
values.push_back(value_wrapper_type(3));
values.push_back(value_wrapper_type(1));
values.push_back(value_wrapper_type(2));
typedef Average<value_type> average_type;
average_type avg;
#if 0
// for loop version:
for(value_vector_type::iterator it = values.begin(); it!=values.end(); it++){
avg(it->getValue()); // I want to put this in a for_each loop
}
#else
// bind version:
std::for_each(values.begin(), values.end(), // iterate over all values
boost::bind(
boost::mem_fn(&average_type::operator()), // attach the averaging functor to the output of the getvalue call
&avg,
boost::bind(
boost::mem_fn(&value_wrapper_type::getValue), // bind the getValue call to each element in values
_1
)
)
);
#endif
std::cout << "Average: " << avg.getAverage() << " Count: " << avg.getCount() << " Sum: " << avg.getSum() << std::endl;
}
注意:我最初的问题是如何构建一个 for_each,但我发现这个解决方案和一个全新的问题没有多大意义。
谢谢,非常感谢所有帮助!
【问题讨论】:
-
为什么?这完成了什么
std::accumulate(values.begin(), values.end())/values.size();不会做的事情? -
@JerryCoffin Averaging 是一个简化的问题,它提取了我实际问题的本质,即在 for_each 循环中将成员函数绑定到函子。
-
我的观点也意味着更广泛——我认为你采取了错误的方法,你最好问问你在这里真正想要完成什么,而不是您为实现这一目标而开始采取的(可能是错误的,IMO)路径的详细信息。
-
@JerryCoffin 我同意这可能不是最好的方法,但学习一些复杂的 C++ 肯定是有益的。
标签: c++ boost foreach iterator member-functions