virtuales valores usar retornar retornan que punteros puntero poo objeto funciones ejemplo dev declarar como codigo c++ function function-pointers

c++ - valores - ¿Es posible declarar un puntero a una función con un tipo de retorno desconocido(en tiempo de compilación)



puntero a objeto c++ (4)

Tengo una class A en la que quiero tener un puntero a una función como miembro de datos:

class A { protected: double (*ptrToFunction) ( double ); public: ... //Setting function according to its name void SetPtrToFunction( std::string fName ); };

Pero qué ptrToFunction si quiero que ptrToFunction sea ​​a veces double y, a veces, int , tenga algo como:

//T is a typename T(*ptrToFunction) ( double );

¿Cómo debo declararlo en este caso?


Parece que está usando dlsym / GetProcAddress para obtener la dirección de las funciones.

En este caso, necesita al menos 2 sitios de llamadas para desambiguar la llamada, ya que la CPU realmente hace cosas diferentes para cada una de estas llamadas.

enum ReturnType { rtInt, rtDouble }; void SetPtrToFunction( std::string fName , enum ReturnType typeOfReturn ); struct Function { enum ReturnType rt; union { std::function< int(double) > mIntFunction; std::function< double(double) > mDoubleFunction; } u; } mFunction;

Por lo tanto, la función debe ser instanciada con un tipo de retorno conocido, y luego se usa con alguna unión etiquetada para obtener la llamada de función correcta.

int A::doCall( double value ) { if( mFunction.rt == rtInt ) { int result = mFunction.mIntFunction( value ); } else if( mFunction.rt == rtDouble ) { double result = mFunction.mDoubleFunction( value ); } }


Si su clase no tiene una plantilla, como en su ejemplo, podría hacer esto:

template <class T> struct myStruct { static T (*ptrToFunction)(double); };


Una unión discriminada puede hacer eso por ti:

class A { template<T> using cb_type = T(double); protected: enum {IS_INT, IS_DOUBLE} cb_tag; union { cb_type<int> *ptrToIntFunction; cb_type<double> *ptrToDoubleFunction; }; public: ... // Setting function according to its name void SetPtrToFunction( std::string fName ); };

Una solución más general y elegante para una unión discriminada se puede aplicar con std::variant en C ++ 17, o boost::variant para revisiones estándar anteriores.

Alternativamente, si desea ignorar completamente el tipo de retorno, puede convertir el miembro en std::function<void(double)> y beneficiarse de la eliminación de tipos. El concepto Callable verá la llamada a través del puntero convertido en static_cast<void>(INVOKE(...)) y descartará el valor de retorno, sea el que sea.

Para illustrate :

#include <functional> #include <iostream> int foo(double d) { std::cout << d << ''/n''; return 0; } char bar(double d) { std::cout << 2*d << ''/n''; return ''0''; } int main() { std::function<void(double)> cb; cb = foo; cb(1.0); cb = bar; cb(2.0); return 0; }

Y, por último, si le importa el valor de retorno pero no quiere almacenar una unión discriminada. Luego, al conocer las uniones y el comportamiento de la std::function , puede combinar los dos enfoques anteriores.

Me gusta esto

#include <functional> #include <iostream> #include <cassert> int foo(double d) { return d; } double bar(double d) { return 2*d; } struct Result { union { int i_res; double d_res; }; enum { IS_INT, IS_DOUBLE } u_tag; Result(Result const&) = default; Result(int i) : i_res{i}, u_tag{IS_INT} {} Result(double d) : d_res{d}, u_tag{IS_DOUBLE} {} Result& operator=(Result const&) = default; auto& operator=(int i) { i_res = i; u_tag = IS_INT; return *this; } auto& operator=(double d) { d_res = d; u_tag = IS_DOUBLE; return *this; } }; int main() { std::function<Result(double)> cb; cb = foo; auto r = cb(1.0); assert(r.u_tag == Result::IS_INT); std::cout << r.i_res << ''/n''; cb = bar; r = cb(2.0); assert(r.u_tag == Result::IS_DOUBLE); std::cout << r.d_res << ''/n''; return 0; }


posible declarar un puntero a una función con valor de retorno desconocido (en tiempo de compilación)

class Myclass { template<T1> protected: double (*pointertoFunction) ( double ); public: ... void SetPtrToFunction( std::string firstname ); }; struct myStruct // structure or enum which ever ou want { static T1 (*pointertoFunction)(double); };