【问题标题】:Call member functions of members of elements of a container with for_each?用for_each调用容器元素成员的成员函数?
【发布时间】:2009-05-13 12:55:06
【问题描述】:

令人困惑的标题,希望一些代码可以澄清:

struct MyNestedType {
    void func();
};

struct MyType {
    MyNestedType* nested;
}

std::vector<MyType> vec;

// ... populate vec

// I want something approximating this line, but that doesn't use made-up C++!
std::for_each(vec.begin(), vec.end(), std::mem_fun_ref(&MyType::nested->func));

所以基本上我想在容器的每个元素上调用一个方法,但它实际上不是该类型的方法,它是包含类型的某个方法...我知道我可以编写一个函数对象来“传递” ' 调用,但我想调用一些方法,这会变得混乱。

有什么想法吗?

【问题讨论】:

    标签: c++ stl functor foreach


    【解决方案1】:

    为什么不直接使用一个简单的 for 循环?

    for(vector<MyType>::iterator i = vec.begin(); i != vec.end(); ++i)
        i->nested->func();
    

    或者,您可以使用 lambda 表达式或 boost::foreach

    FOREACH(MyType x, vec)
        x.nested->func();
    

    您可以使用 binders 和 mem_funs 构建您的表达式,但这会变得非常混乱和混乱!将所有内容放在一个 std::foreach 行中没有任何优势。

    【讨论】:

    • 当然有优势!它会让我觉得真的很聪明!不过,要点。也许我会像现在一样将其保留为 for 循环。
    • 当然,当我想象 boost::bind 会变得多么混乱时,我首先想到的是 boost::bind :) +1 确实
    【解决方案2】:

    你可以使用这样的函子

    template <typename T, T* MyType::* TMember, void (T::* TNestedMember)() >
    struct Caller {
        Caller() {
        }
    
        template <typename TObject>
        void operator()(TObject object) {
            (object.*TMember->*TNestedMember)();
        }
    };
    

    解决你的问题

    struct MyNestedType {
        MyNestedType(int a):
            a_(a){
        }
        void func() {
            std::cout << "MyNestedType::func " << a_ << std::endl;
        }
        void foo() {
            std::cout << "MyNestedType::foo " << a_ << std::endl;
        }
        int a_;
    };
    struct MyType {
        MyNestedType* nested;
    };
    
    int main()
    {
        std::vector<MyType> vec;
    
        std::auto_ptr<MyNestedType> nt1(new MyNestedType(2));
        std::auto_ptr<MyNestedType> nt2(new MyNestedType(5));
        MyType t1 = {nt1.get()};
        MyType t2 = {nt2.get()};
    
        vec.push_back(t1);
        vec.push_back(t2);
    
        std::for_each(vec.begin(), vec.end(), 
                      Caller<MyNestedType, &MyType::nested, &MyNestedType::func>());
        std::for_each(vec.begin(), vec.end(), 
                      Caller<MyNestedType, &MyType::nested, &MyNestedType::foo>());
    }
    

    【讨论】:

    • 太棒了,这正是我所希望的答案,尽管其他一些 cmets 让我觉得也许我在寻找错误的东西 ;)
    • 好答案,您猜到 Ben 想要参数化方法和嵌套成员对象,尽管没有说明。
    • 不必刻薄。如果我写的是“&MyType::nested::MyNestedType::func”而不是“&MyType::nested->func”会更清楚吗?我以为我在推动伪 C++ 的极限!
    【解决方案3】:

    也许你可以将 func() 添加到 struct MyType() 中:

    void func(...) {
       nested->func(...);
    }
    

    这样你就不会有单独的适配器仿函数,而是在包装器类型中进行聚合,即非常常规的 OOP 技术。

    【讨论】:

    • 一个红润的好点。我已经接受了另一个答案,因为它回答了这个问题,但我评价了这个答案,因为这是我可能会接受的建议!
    【解决方案4】:

    如果你想使用 for_each,你需要一个仿函数。

    struct CallMyFunc
    {
        void operator()(MyType& obj)    {   obj.nested->func();}
    };
    
    
    std::for_each(vec.begin(), vec.end(), CallMyFunc());
    

    或者,我会使用以下描述的 boost::FOREACH 语法:

    达里奥:Call member functions of members of elements of a container with for_each?

    【讨论】:

      【解决方案5】:

      是的,可以为此使用boost::bind,但它会变得混乱。请使用@Dario 的boost for-each 方式,但为了完整起见,这里是boost::bind 一个

      std::for_each(vec.begin(), vec.end(), 
          boost::bind(&MyNestedType::func, boost::bind(&MyType::nested, _1)));
      

      无论如何,碰巧的是,我们甚至没有得到一个很好的单线:)

      【讨论】:

        【解决方案6】:

        使用 Boost 的 transform_iterator 怎么样?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-05-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-06-30
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多