我们正在过渡到C ++ 11但仍然需要几个月的时间。请随意给出C ++ 11的回复,但我们很好奇在C ++ 98/03中是否有一种非丑陋的方式。
一位同事带着类似的代码来找我:
typedef void(B::*fptr_t)();
void A::my_foreach( uint idx, fptr_t fptr ) {
for( iter_type iter = asdf[idx].begin(); iter != asdf[idx].end(); ++iter )
iter->second->*fptr();
}
void A::get( uint idx ) { my_foreach( idx, &B::get ); }
void A::get( uint idx ) { my_foreach( idx, &B::get ); }
...询问是否有更好的方式,我回答:
void A::get( uint idx ) {
std::for_each( asdf[idx].begin()
, asdf[idx].end()
, boost::bind( &B::get, _1 ) );
}
void A::put( uint idx ) {
std::for_each( asdf[idx].begin()
, asdf[idx].end()
, boost::bind( &B::put, _1 ) );
}
...但仍然让我觉得可以采取更多措施来避免代码重复。我遇到的一般解决方案是:
apply to my container
成员函数(即调用者必须提供函数)boost::bind
包装整个内容,制作一个可以像这样使用的仿函数:
functor_t get = my_binder( &B::get );
functor_t put = my_binder( &B::put );
...其中my_binder
会生成一个可以执行相同操作的对象,但由于上述代码中实际执行了多少函数,因此很快变得丑陋(operator[]
,{{1 }},X::begin
,X::end
)。
在C ++ 11之前是否有其他/更好的方法,或者那些解决方案几乎可用?
答案 0 :(得分:1)
std::mem_fn
是步骤4中的活页夹。
您并未完全提及您的容器看起来是关联的(例如std::map
)。我建议使用Boost Range来调整范围以投影到映射值:
<强> Live On Coliru 强>
#include <boost/range/algorithm.hpp>
#include <boost/range/adaptors.hpp>
using namespace boost::adaptors;
template<typename T> struct Container {
template <typename F> void my_foreach(uint idx, F&& f) {
boost::for_each(_data[idx] | map_values, std::forward<F>(f));
}
std::map<int, std::map<int, T> > _data;
};
#include <iostream>
struct B {
B(std::string s) : _s(s) {}
void foo() const { std::cout << "foo(" << _s << ")\n"; }
void bar(int i) const { std::cout << "bar(" << _s << ", " << i << ")\n"; }
private:
std::string _s;
};
#include <functional>
int main() {
Container<B> c;
c._data = { // just some demo data
{ 1, { { 100, {"hundred"} }, { 1000, {"thousand"} }, { 1000000, {"million"} }, } },
{ 2, { { 100, {"hundert"} }, { 1000, {"tausend"} }, { 1000000, {"miljon"} }, } },
{ 3, { { 100, {"cent"} }, { 1000, {"mille"} }, { 1000000, {"million"} }, } },
{ 4, { { 100, {"honderd"} }, { 1000, {"duizen"} }, { 1000000, {"miljoen"} }, } },
};
c.my_foreach(3, std::mem_fn(&B::foo));
c.my_foreach(1, [](B const& b) { b.bar(42); });
}
印刷:
foo(cent)
foo(mille)
foo(million)
bar(hundred, 42)
bar(thousand, 42)
bar(million, 42)