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

发布于 2024-07-19 12:12:37 字数 476 浏览 3 评论 0原文

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

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

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

有任何想法吗?

Confusing title, hopefully some code will clarify:

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

So basically I want to call a method on each element of the container, but it's not actually a method of the type, it's some method on a contained type... I know I could write a function object to 'pass on' the call but there are a few methods I'd like to call and that will get messy.

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

甜宝宝 2024-07-26 12:12:37

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

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

Why don't you just use a simple for-loop?

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

Alternatively, you could use lambda expressions or boost::foreach

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

You can build your up expression with binders and mem_funs, but this will get very messy and confusing! There is no advantage in putting everything in one std::foreach line.

疑心病 2024-07-26 12:12:37

您可以使用这样的函子

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

You can use such functor

template <typename T, T* MyType::* TMember, void (T::* TNestedMember)() >
struct Caller {
    Caller() {
    }

    template <typename TObject>
    void operator()(TObject object) {
        (object.*TMember->*TNestedMember)();
    }
};

To solve your problem

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>());
}
寒尘 2024-07-26 12:12:37

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

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

这样你就不会拥有单独的适配器函子,而是包装类型内的聚合,即相当常规的 OOP 技术。

Maybe you could add func() into struct MyType():

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

This way you will not have separate adapter functor, but instead an aggregation inside wrapper type, i.e. quite regular OOP technique.

淡看悲欢离合 2024-07-26 12:12:37

如果你想使用 for_each 你需要一个函子。

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


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

描述的 boost::FOREACH 语法

或者,我会使用Dario: 使用 for_each 调用容器元素成员的成员函数?

If you want to use for_each you need a functor.

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


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

Alternatively I would use the boost::FOREACH syntax described by:

Dario: Call member functions of members of elements of a container with for_each?

岁月如刀 2024-07-26 12:12:37

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

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

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

Yes it is possible to use boost::bind for this, but it gets messy. Please use @Dario's boost for-each way, but here is the boost::bind one for the sake of completeness

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

Anyway, as it happens, we don't even get a nice one-liner with this :)

小梨窩很甜 2024-07-26 12:12:37

How about using Boost's transform_iterator?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文