在C聚合类中实现调用多路复用的优雅方式?

当多路调用多个子对象时,什么是阻止循环样板代码的优雅方法

问题描述示例:

struct Foo {
  void Boo();
  void Hoo();
  bool IsActivated();
};

struct FooAggregator {
  ...
  void Boo();
  void Hoo();
  ...
  std::vector<Foo> m_foos;
};

FooAggregator::Boo() {
  for(size_t i=0,e=m_foos.size(); i!=e; ++i) {
    if(m_foos[i].IsActivated()) {
      m_foos[i].Boo();
    }
  }
}

FooAggregator::Hoo() {
  for(size_t i=0,e=m_foos.size(); i!=e; ++i) {
    if(m_foos[i].IsActivated()) {
      m_foos[i].Hoo();
    }
  }
}

如您所见,FooAggregator实现与单个Foo相同(相似)的接口,迭代调用其各自成员函数的所有Foo对象.

正如您所看到的,迭代循环是完整的样板,为FooAggregator的每个成员函数重复.

从FooAggregators成员函数的实现中删除样板的优雅方法是什么

解决方法

您可以使用Boost.Bind作为@Space_C0wb0y建议.但是如果你出于某种原因不能使用它,那么你可以做这样的事情:
struct FooAggregator 
{
    typedef void (Foo::*Fun)();


    void Boo() {  CallForEach(m_foos.begin(),m_foos.end(),&Foo::Boo); }
    void Hoo() {  CallForEach(m_foos.begin(),&Foo::Hoo); }

    template<typename FwdIterator>
    void CallForEach(FwdIterator first,FwdIterator last,Fun fun)
    {
        while (first != last ) 
        { 
            if(first->IsActivated())
            {
                 (first->*fun)();
            }
            first++;
        }
    }
};

或者您可以使用< algorithm>中的std :: for_each如:

#include <algorithm>

struct FooAggregator 
{
    typedef void (Foo::*Fun)();

    void Boo() {  std::for_each(m_foos.begin(),Call(&Foo::Boo)); }
    void Hoo() {  std::for_each(m_foos.begin(),Call(&Foo::Hoo)); }

    struct Call
    {
        Fun m_fun;
        Call(Fun fun) : m_fun(fun) {}
        void operator()(Foo & foo)
        {
            if(foo.IsActivated())
            {
               (foo.*m_fun)();
            }
        }
   };    
};

阅读约Function object以了解第二个例子.

在C 0x(即C 11)中,它非常简单.您可以在std :: for_each中使用lamda:

#include <algorithm>

struct FooAggregator 
{
    void Boo()
    {  
         std::for_each(m_foos.begin(),[](Foo &foo){ if (foo.IsActivated()) foo.Boo(); } ); 
    }

    void Hoo()
    {  
         std::for_each(m_foos.begin(),[](Foo &foo){ if (foo.IsActivated()) foo.Hoo(); } ); 
    }
    //other code
};

相关文章

对象的传值与返回说起函数,就不免要谈谈函数的参数和返回值...
从实现装饰者模式中思考C++指针和引用的选择最近在看...
关于vtordisp知多少?我相信不少人看到这篇文章,多半是来自...
那些陌生的C++关键字学过程序语言的人相信对关键字并...
命令行下的树形打印最近在处理代码分析问题时,需要将代码的...
虚函数与虚继承寻踪封装、继承、多态是面向对象语言的三大特...