简体   繁体   中英

c++ std for_each define the std function later

I want to change this code:

std::for_each( container.begin(), container.end(), std::bind(&Class::method1, _1, param));

where the container has pointers to Class, to a version that you would only pass the param:

// create the functor here ( bind to method1 or method2, etc)
// ....
//
std::for_each( container.begin(), container.end(), functor(param) );

I can't use lambdas.

The container can be:

 std::list<Class*>
struct functor {
    int param;
    functor(int param): param(param) {}
    void operator()(Class* c) {
        c->method1(param);
    }
};

There you go. A functor class that you can use exactly as your example. No lambda, no bind to a method. Just pass the parameter to the constructor. You can pass a member function pointer to the constructor or expand this to a template to avoid writing one for each method.

Or if you simply wanted to choose the method first and bind the parameter later, you could do this:

// create the functor here ( bind to method1 or method2, etc)
std::function<void(Class*,decltype(param))> functor(&Class::method1); // "bind" the method
// ....
std::for_each( container.begin(), container.end(), std::bind(functor, _1, param) ); // bind the param

Note that I don't see any advantage to doing this instead of the first line of code in your question.

You want something to make the functor.

This is the general functor you are going to want.

template< typename CLASS, typename CLASS_METHOD, typename PARAM_TYPE >
class Functor
{
    CLASS_METHOD m_method; // actually will be of type void(CLASS::*func)( PARAM_TYPE )

    PARAM_TYPE m_param;

 public:
    void operator()( CLASS * c ) const
    {
       (c->*m_method)( m_param );
    }
};

template typename< CLASS, CLASS_METHOD, PARAM_TYPE > 
Functor< CLASS, CLASS_METHOD, PARAM_TYPE > 
functor( CLASS_METHOD method, PARAM_TYPE param )
{
      return Functor< CLASS, CLASS_METHOD, PARAM_TYPE >( method, param );
}

std::for_each
  ( 
    container.begin(), container.end(), 
    functor< Class >( &Class::method1, param );
  );

We can make it non-template if you prefer.

class Functor
{
     typedef void (Class::*func_type )(int);

     func_type m_method; // assuming that's the param type
     int m_param;

public:
     Functor( func_type method, int param )
         : m_method( method ), m_param( param )
     {
     }

     void operator()( Class * c ) const
     {
        (c->*m_method)(param);
     }
};

std::for_each( container.begin, container.end(), Functor( &Class::method1, param ) );

Now to "only" specify the param, you write functions for each "method" thus:

Functor method1Functor( int param )
{
      return Functor( &Class::method1, param );
}

Functor method2Functor( int param )
{
    return Functor( &Class::method2, param );
}

In your code now:

std::for_each( container.begin(), container.end(), method1Functor( param ) );

You could also write these function methods to do a bind and return a std::function .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM