如何使用for_each调用容器中元素的成员函数?

4
混淆的标题,希望代码能够澄清:

令人困惑的标题,希望通过代码来澄清:

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));

我希望对一个容器中的每个元素都调用一个方法,但是该方法并非类型本身的方法,而是该类型中包含的某种方法... 我知道我可以编写函数对象来"传递"调用,但有几种方法我想要调用,那样会很混乱。

有什么好的想法吗?

6个回答

6
为什么不使用简单的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();

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

1
当然有优势!这会让我感觉非常聪明!不过你说得对。也许我应该像现在这样把它留作一个for循环。 - Ben Hymers
当我想象使用boost::bind会变得多么混乱时,boost foreach是我的第一个想法。确实+1。 - Johannes Schaub - litb

3
您可以使用这样的函数对象。
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>());
}

太棒了,这正是我所期望的答案,尽管其他评论让我觉得也许我在寻找错误的东西 ;) - Ben Hymers
好的答案,你推断出Ben想要对方法和嵌套成员对象进行参数化,尽管没有明确说明。 - veefu
请不要挖苦。如果我写成"&MyType::nested::MyNestedType::func"而不是"&MyType::nested->func",会更清晰吗?我认为我已经在尽可能使用伪C++了! - Ben Hymers

2
也许您可以将func()添加到结构MyType()中:
void func(...) {
   nested->func(...);
}

这样,您将不会有单独的适配器函数,而是在包装类型内部进行聚合,也就是相当常见的面向对象编程技术。

一个非常好的观点。我已经接受了另一个答案,因为它回答了问题,但我给这个答案升了评级,因为这可能是我要采纳的建议! - Ben Hymers

2

如果您想使用for_each,您需要一个函数对象。

struct CallMyFunc
{
    void operator()(MyType& obj)    {   obj.nested->func();}
};


std::for_each(vec.begin(), vec.end(), CallMyFunc());

此外,我会使用 boost::FOREACH 语法,该语法由以下人员描述:

Dario: 如何使用 foreach 调用容器元素的成员函数?


2

是的,可以使用boost::bind来实现这个功能,但会变得很混乱。请使用@Dario的boost for-each方法,但为了完整起见,这里提供boost::bind的方法。

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

无论如何,事实上,我们甚至没有得到一个漂亮的一行代码 :)

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接