2012-09-13 17 views
6

Decir que tengo estas 3 funciones diferentes que yo quiero señalar a:El uso de std :: función como delegado en C++ 11

float test1(int a, int b) { 
    return 7.0f; 
} 

struct TestClass { 
    float test2(int a, int b) { 
     return 5.0f; 
    } 
}; 

struct TestClass2 { 
    float test3(int a, int b) { 
     return 3.0f; 
    } 
}; 

Observe cómo los tres utilizan los mismos argumentos y valor de retorno. Quiero resumir si es o no una función miembro y a qué clase pertenecía. Quiero un tipo de delegado que podría referirse a cualquiera de estas 3 funciones dependiendo únicamente de cómo se inicializó.

Aquí es mi primer intento:

typedef std::function<float(int, int)> MyDelegate; // is this right? 

int main() { 
    TestClass obj; 
    TestClass2 obj2; 

    MyDelegate a = test1; 
    MyDelegate b = std::bind(std::mem_fn(&TestClass::test2), obj); // is this right? 
    MyDelegate c = std::bind(std::mem_fn(&TestClass2::test3), obj2); // is this right? 

    return 0; 
} 

La idea es que quiero almacenar también el 'este' puntero dentro de la envoltura también. De esta forma, es como un delegado totalmente funcional. Por ejemplo, invocar 'b (x, y)' debería ser como llamar al obj.test2(x, y).

Simplemente no puedo hacer que compile, probablemente no estoy entendiendo esto completamente. Soy nuevo en estas bibliotecas y los errores en VS2012 son catastróficamente inútiles. Cualquier ayuda sería apreciada.

+0

posible duplicado de [C++ 11 devoluciones de llamada de estilo?] (Http://stackoverflow.com/questions/12338695/c11-styled-callbacks) – Klaim

Respuesta

9

Debe indicar std::bind qué hacer con los otros parámetros de la función. Con el fin de hacer la llamada b(x, y) delegado x y y a los dos parámetros de la función original que se necesita para utilizar marcadores de posición de la std::placeholders espacio de nombres:

std::bind(&TestClass::test2, obj, std::placeholders::_1, std::placeholders::_2); 

Y tampoco hay necesidad de std::mem_fn (funciona, sin embargo), ya que std::bind ya maneja correctamente las funciones miembro (haciendo que el argumento implícito this sea un primer argumento explícito, como std::mem_fn).

3

es necesario proporcionar argumentos a 2 std :: bind o proporcionar marcadores de posición para proporcionarles más tarde:

std::function<float(int, int)> c = std::bind(&TestClass2::test3, obj2, 1, 2); 
c(); //returns result 

O

std::function<float(int, int)> c = std::bind(&TestClass2::test3, obj2, std::placeholders::_1, std::placeholders::_2); 
c(1, 2); //returns result 

Más información sobre std :: bind es here.

2

Utilizando Visual C++ Compiler (CTP 2012) Espié cómo lo hicieron std :: función y deliviered mi propia solución para manejar las funciones miembro

uso se ve así: http://ideone.com/v5zfDn

class Window 
{ 
public: 
    void Show(int number) const 
    { 
     //... 
    } 

    void ShowDynamic(int number) volatile 
    { 
     //... 
    } 
}; 

void ShowWindows(int param) 
{ 
    //... 
} 

int main() 
{ 
    Window window; 

    typedef mezutils::Delegate< void(int) > Notifier; 
    Notifier notifier; 

    notifier = &ShowWindows; 
    notifier(0); 

    notifier = Notifier(&window, &Window::Show); 
    notifier(1); 

    notifier = [](int x) { /*...*/ }; 
    notifier(2); 

    void (*funpc)(int) = func; 
    notifier = funpc; 
    notifier(3); 

    notifier = [](int arg) { printf("asd %d\r\n",arg); }; 
    notifier(4); 
    return 0; 
} 

miradas clase Delegate como: http://ideone.com/DebQgR

por supuesto que es un prototipo hecho por diversión, pero me gusta porque está claro

Cuestiones relacionadas