在 C++03 中将成员函数传递给 for_each (无 boost,无 c++11)

发布于 2024-10-11 11:10:53 字数 617 浏览 0 评论 0原文

下面的“解决方案”可以编译,但这不是我想要的。我想将 put 成员函数传递给 for_each 而不是 *this。使用 boost 不是一个选项。这可以在 C++03 中解决吗?

#include <algorithm>
#include <functional>
#include <vector>
using namespace std;

class Wheel { };

class Car {

public:

    void process(const vector<Wheel>& wheel) {

        for_each(wheel.begin(), wheel.end(), *this);
    }

    void operator()(const Wheel& w) { put(w); }

private:

    void put(const Wheel& w) { }
};

int main() {

    vector<Wheel> w(4);

    Car c;

    c.process(w);

    return 0;
}

The "solution" below compiles but it is not what I want. I would like to pass the put member function to for_each and not *this. Using boost is NOT an option. Can this be solved within C++03?

#include <algorithm>
#include <functional>
#include <vector>
using namespace std;

class Wheel { };

class Car {

public:

    void process(const vector<Wheel>& wheel) {

        for_each(wheel.begin(), wheel.end(), *this);
    }

    void operator()(const Wheel& w) { put(w); }

private:

    void put(const Wheel& w) { }
};

int main() {

    vector<Wheel> w(4);

    Car c;

    c.process(w);

    return 0;
}

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

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

发布评论

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

评论(3

莫言歌 2024-10-18 11:10:53

是的,可以,使用 mem_funbind1st 模板的组合:

void process(const vector<Wheel>& wheel) {
    for_each(wheel.begin(), wheel.end(), bind1st(mem_fun(&Car::put), this));
}

mem_fun 的调用创建一个新的函数对象,它接受两个参数 -一个 Car* 充当接收器和一个 Wheel,然后调用 put,第一个参数作为接收器,第二个参数作为实参。然后调用 bind1st 将接收者对象锁定为该函数的第一个参数。

但是,我认为您需要对此代码进行一点小小的更改才能使其正常工作。 bind1st 适配器不能很好地与通过 const 引用获取参数的函数配合使用,因此您可能需要更改 put 以便它需要Wheel 按值而不是按引用。

Yes it can, using a combination of the mem_fun and bind1st templates:

void process(const vector<Wheel>& wheel) {
    for_each(wheel.begin(), wheel.end(), bind1st(mem_fun(&Car::put), this));
}

The call to mem_fun creates a new function object that takes in two arguments - a Car* to act as the receiver and a Wheel, then calls put with the first parameter as the receiver and the second parameter as the argument. Calling bind1st then locks the receiver object as first parameter of this function in place.

However, I think you will need to make one small change to this code to get it to work. The bind1st adapter doesn't play well with functions that take their arguments by const reference, so you might need to change put so that it takes a Wheel by value rather than by reference.

紧拥背影 2024-10-18 11:10:53

您可以使用 mem_fun_ref:请参阅此处

mem_fun_ref 应该适用于您有对象向量的情况:

for_each(wheel.begin(), wheel.end(), mem_fun_ref(&Wheel::put));

请注意,上面的示例将 put 更改为 Wheel 而不是 Car 的成员。它应该能让您了解如何使用它。

如果您有指向对象的指针向量,请使用mem_fun

You can use mem_fun_ref: see here.

mem_fun_ref should work in your case where you have vector of objects:

for_each(wheel.begin(), wheel.end(), mem_fun_ref(&Wheel::put));

Note that the above example changes put to be a member of Wheel and not Car. It should give you an idea of how to use it though.

Use mem_fun if you have a vector of pointers to an object

灵芸 2024-10-18 11:10:53

当然,您可以编写自己的 boost::mem_func 等价物。 TR1也有一个。如果您想要增加参数数量,这有点重复,但概念上并不困难。

template<typename T, typename mem_func_type> struct mem_func_internal;
template<typename T, typename Ret> struct mem_func_internal<T, Ret (T::*)()> {
    typedef Ret(T::* functype)();
    T* obj;
    functype func;
    Ret operator()() {
        return obj->*func();
    }
};
template<typename T, typename Ret, typename ArgType1> struct mem_func_internal<T, Ret (T::*)(ArgType1) {
    typedef Ret(T::* functype)();
    T* obj;
    functype func;
    Ret operator()(ArgType1 arg) {
        return obj->*func(arg);
    }
 }
template<typename T, typename mem_func_type> struct mem_func : public mem_func_internal<T, mem_func_type> {
    mem_func(T* object, mem_func_type mem_func)
        : obj(object)
        , func(mem_func) {}
};
template<typename T, typename mem_func_type> mem_func<T, mem_func_type> bind_mem_func(T* object, mem_func_type func) {
    return mem_func<T, mem_func_type>(object, func);
}
// Usage
std::for_each(wheel.begin(), wheel.end(), bind_mem_func(this, &Car::put));

自从我写这样的代码已经有一段时间了,所以可能有点不对劲。但这就是要点。如果不使用 lambda 就很难编写用法示例。

Sure- you can just write your own equivalent of boost::mem_func. TR1 has one too. It's a little repetitive if you want increasing numbers of arguments, but not conceptually hard.

template<typename T, typename mem_func_type> struct mem_func_internal;
template<typename T, typename Ret> struct mem_func_internal<T, Ret (T::*)()> {
    typedef Ret(T::* functype)();
    T* obj;
    functype func;
    Ret operator()() {
        return obj->*func();
    }
};
template<typename T, typename Ret, typename ArgType1> struct mem_func_internal<T, Ret (T::*)(ArgType1) {
    typedef Ret(T::* functype)();
    T* obj;
    functype func;
    Ret operator()(ArgType1 arg) {
        return obj->*func(arg);
    }
 }
template<typename T, typename mem_func_type> struct mem_func : public mem_func_internal<T, mem_func_type> {
    mem_func(T* object, mem_func_type mem_func)
        : obj(object)
        , func(mem_func) {}
};
template<typename T, typename mem_func_type> mem_func<T, mem_func_type> bind_mem_func(T* object, mem_func_type func) {
    return mem_func<T, mem_func_type>(object, func);
}
// Usage
std::for_each(wheel.begin(), wheel.end(), bind_mem_func(this, &Car::put));

It's been a while since I wrote code like this, so it might be a little off. But that's the gist of it. So hard to write a usage example without just using a lambda.

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