2012-03-15 18 views
5

¿Sabría si hay una forma de pasar argumentos usando std :: mem_fun? Quiero precisar que puedo tener tantos argumentos como sea posible y muchas funciones miembro.
El problema es que estoy en un estándar antiguo y estoy buscando una forma completa stl así que no estoy permitido como respuesta incluso si sé que podría hacerlo fácilmente =/Cómo pasar argumentos usando std :: mem_fun

Aquí hay un poco ilustración de cómo quiero usarlo:

#include <list> 
#include <algorithm> 

// Class declaration 
// 
struct Interface { 
    virtual void run() = 0; 
    virtual void do_something(int) = 0; 
    virtual void do_func(int, int) = 0; 
}; 

struct A : public Interface { 
    void run() { cout << "Class A : run" << endl; } 
    void do_something(int foo) { cout << "Class A : " << foo << endl; } 
    void do_func(int foo, int bar) { cout << "Class A : " << foo << " " << bar << endl; } 
}; 

struct B : public Interface { 
    void run() { cout << "Class B : run" << endl; } 
    void do_something(int foo) { cout << "Class B : " << foo << endl; } 
    void do_func(int foo, int bar) { cout << "Class B : " << foo << " " << bar << endl; } 
}; 

// Main 
// 
int main() { 
    // Create A and B 
    A a; 
    B b; 

    // Insert it inside a list 
    std::list<Interface *> list; 
    list.push_back(&a); 
    list.push_back(&b); 

    // This works 
    std::for_each(list.begin(), list.end(), std::mem_fun(&Interface::run)); 

    // But how to give arguments for those member funcs ? 
    std::for_each(list.begin(), list.end(), std::mem_fun(&Interface::do_something)); 
    std::for_each(list.begin(), list.end(), std::mem_fun(&Interface::do_func)); 
    return 0; 
} 

Respuesta

11

Uso std::bind través std::bind1st y std::bind2nd

std::for_each(list.begin(), list.end(), 
       std::bind2nd(std::mem_fun(&Interface::do_something),1) // because 1st is this 
      ); 

Por desgracia, la norma no ayuda para la versión de dos argumentos y lo que necesita para escribir su propia:

struct MyFunctor 
{ 
    void (Interface::*func)(int,int); 
    int   a; 
    int   b; 

    MyFunctor(void (Interface::*f)(int,int), int a, int b): func(f), a(a), b(b) {} 

    void operator()(Interface* i){ (i->*func)(a,b);} 
}; 

std::for_each(list.begin(), list.end(), 
       MyFunctor(&Interface::do_func, 1, 2) 
      ); 
1

Ver std::bind1st y std::bind2nd. Son bastante torpes y feas de usar, pero si insistes en usar solo lo que está presente en C++ 03 sin ninguna adición, son prácticamente todo lo que está disponible.

Editar: cuando/si tengo que hacer esto, generalmente lo hago con una pequeña clase de funtor en lugar de usar std::bind1st y/o std::bind2nd. En última instancia, esto no es muy diferente de lo que generan, pero (IMO) generalmente es más legible.

template<class T> 
class invoke_do_something { 
    int value; 
public: 
    adder(int x) : value(x) {} 
    void operator()(T &t) { 
     t.do_something(value); 
    } 
}; 

std::for_each(list.begin(), list.end(), invoke_do_something(1)); 

Mi propia opinión, sin embargo, es que la mayoría de las veces esto es una especie de curita. Ocurre constantemente usando for_each. Normalmente me parece que con un poco de pensamiento, puedo encontrar un algoritmo más adecuado, que con frecuencia elimina la necesidad de algo en este orden en absoluto.

+0

Gracias por su respuesta, ¿puede poner un ejemplo de cómo usarlo ? No puedo hacer que funcione .. – klefevre

+0

Supongo que podría, pero 1) @LokiAstari ya lo tiene, así que no agregaría mucho, y 2) Nunca los uso. Hace mucho tiempo decidí que no valían la pena. En la (sorprendentemente rara) situación en la que necesito ese tipo de cosas, escribo una pequeña clase de functor para manejarlo. Afortunadamente, en C++ 11, es fácil eliminar eso también. –

+0

Gracias de todos modos. – klefevre

1

Puede uniéndose:

using std::placeholders::_1 
int a; 
std::for_each(list.begin(), list.end(), std::bind(&Interface::do_something, _1, a)); 
+2

Está en "un antiguo estándar", es decir 98 o 03. Esto es C++ 11. – MSalters

+0

@MSalters: notamos que, sin embargo, C++ 11 es taaaan el año pasado. –

Cuestiones relacionadas