2012-04-20 22 views
6

Me gustaría tener una clase implementar operator() de diferentes maneras según una opción establecida en la clase. Como esto se llamará una gran cantidad de veces, no quiero usar nada que se ramifique. Idealmente, el operator() sería un puntero de función que se puede establecer con un método. Sin embargo, no estoy seguro de cómo se vería realmente. Probé:Operador como puntero de función

#include <iostream> 

class Test { 
public: 
    int (*operator())(); 

    int DoIt1() { 
    return 1; 
    } 

    int DoIt2() { 
    return 2; 
    } 

    void SetIt(int i) { 
    if(i == 1) { 
     operator() = &Test::DoIt1; 
    } else { 
     operator() = &Test::DoIt2; 
    } 
    } 
}; 

int main() 
{ 
    Test t1; 

    t1.SetIt(1); 

    std::cout << t1() << std::endl; 

    t1.SetIt(2); 

    std::cout << t1() << std::endl; 

    return 0; 
} 

Sé que va a funcionar si se crea otro puntero de función y llamar a que a partir de la función operator(). Pero, ¿es posible que la función operator() sea un puntero a la función? Algo parecido a lo que publiqué (que no compila)

El código anterior da:

test.cxx:5:21: error: declaration of ‘operator()’ as non-function

test.cxx: In member function ‘void Test::SetIt(int)’:

test.cxx:17:16: error: ‘operator()’ not defined

test.cxx:19:16: error: ‘operator()’ not defined

test.cxx: In function ‘int main()’:

test.cxx:30:19: error: no match for call to ‘(Test)()’

test.cxx:34:19: error: no match for call to ‘(Test)()’

+0

'int (operador())();' ... sintaxis correcta? – iammilind

+0

Hrm, debería ser 'int (* operator())();' Creo, pero eso solo genera un conjunto de otros errores. Editaré el código. – tpg2114

+0

"No quiero usar nada que se ramifique. Idealmente, el operador() sería un puntero a la función" - En realidad, las ramas son mejores para el rendimiento. Las CPU modernas tienen una tasa de éxito superior al 50% al predecir qué rama se tomará; Los punteros de función pueden apuntar a cualquier lugar y, por lo tanto, son mucho más difíciles en la lógica de predicción. – MSalters

Respuesta

5

Su clase tiene que recordar lo que de alguna manera puntero de función a utilizar. Almacenarla como un miembro de la clase:

class Test 
{ 
public: 
    Test() : func(0) {} 

    int operator()() { 
     // Note that pointers to Test member functions need a pointer to Test to work. 
     return (this->*func)(); // undefined behavior if func == 0 
    } 

    void SetIt(int i) { 
     if(i == 1) { 
      func = &Test::DoIt1; 
     } else { 
      func = &Test::DoIt2; 
     } 
    } 

private: 
    int DoIt1() { 
     return 1; 
    } 

    int DoIt2() { 
     return 2; 
    } 

    // Typedef of a pointer to a class method. 
    typedef int (Test::*FuncPtr)(); 
    FuncPtr func; 
}; 

Sin embargo, antes de entrar en el esfuerzo de hacer esto, perfil de su código de primera y ver si ramificación a través de switch o if es en realidad un cuello de botella (puede que no sea!) Los procesadores modernos tienen características de rendimiento muy intuitivas, por lo que los compiladores pueden generar mejores códigos de lo que crees. La única forma de asegurarse de que la bifurcación sea realmente demasiado costosa para que la use es perfilar su código. (Y al "perfilar" quiero decir "ejecutar experimentos bien diseñados", no "tener una corazonada sin probar").

+0

'typedef int (* FuncPtr)(); 'es incorrecto. Necesita escribir 'typedef int (Test :: * FuncPtr)(); ' – Nawaz

+0

@Nawaz: Solucionado. Gracias por señalar eso. –

+0

Todavía hay problema. Necesita escribir '(this -> * func)();', no solo 'func();'. – Nawaz

1

Puede hacer que su operator() sea una función en línea que llama a otro puntero. El optimizador debería eliminar por completo la indirección adicional.

1

Una solución es provista por @In silico que es válida tanto en C++ 03 como en C++ 11.

Aquí es otra solución para C++ 11 solamente:

std::function<int(Test*)> func; 

func = &Test::DoIt1; 

func(this); //this syntax is less cumbersome compared to C++03 solution 

A quick online full demo

Cuestiones relacionadas