How to use a function of own class in for_each met

2020-03-06 05:25发布

Assume I have this class (inherited from std::Vector, it's just an example)

#include <vector>

using namespace std;

template <class T>
class C : public vector<T> {

    // I don't want to use static keyword
    void transformation(T i) {
        i *= 100;
    }

    public:   
    void method() {
        for_each(this->begin(), this->end(), transformation);
    }
};

int main() {
    C<double> c;
    for (int i=-3; i<4; ++i) {
        c.push_back(i);
    }

    c.method();
}

How do I call for_each using class method inside class itself? I know I can use static keyword, but what is there any other way how to use a function object without using static?

I get this error message while compiling:

for_each.cc:21:55: error: cannot convert ‘C::transformation’ from type ‘void (C::)(double)’ to type ‘void (C::*)(double)’ for_each(this->begin(), this->end(), transformation);

I think I need to add .* or ->* somewhere but I can't find out where and why.

3条回答
男人必须洒脱
2楼-- · 2020-03-06 06:07

C++11 bind solution:

std::for_each(this->begin(), this->end(),
      std::bind(&C::transformation, this, std::placeholders::_1));

C++11 lambda solution:

std::for_each(this->begin(), this->end(),
      [this] (T& i) { transformation(i); });

C++14 generic lambda solution:

std::for_each(this->begin(), this->end(),
      [this] (auto&& i) { transformation(std::forward<decltype(i)>(i)); });

C++98 bind1st+mem_fun solution:

std::for_each(this->begin(), this->end(),
      std::bind1st(std::mem_fun(&C::transformation), this));

Note: this->begin() and this->end() calls are qualified with this-> only because in the OP's code they are member functions of a templated base class. As such, those names are primirarily searched in a global namespace. Any other occurrence of this is mandatory.

查看更多
爷、活的狠高调
3楼-- · 2020-03-06 06:18

You need to bind the this pointer:

public:   
void method() 
{
    for_each(this->begin(), this->end(), bind(&C::transformation, this, placeholders::_1));
}
查看更多
Ridiculous、
4楼-- · 2020-03-06 06:25

For starters, don't inherit from the standard containers, they are not designed to be inherited (no virtual destructors etc.).

Secondly, and regarding your problem, it's because a pointer to a member function is not the same as a pointer to a function. The reason is that member function has a hidden first parameter which becomes the this pointer in the function. The simplest way to solve it is to make the function static.

Another solution is to use the std::bind function that came with C++11:

for_each(this->begin(), this->end(),
    std::bind(&C::transformation, this, std::placeholders::_1));

If you don't have C++11 (even though you tagged your question as such), then you probably could get something working with std::mem_fun or std::bind1st.

查看更多
登录 后发表回答