tipos - Operador de conversión C++ para convertir puntero a función
tipos de datos en c++ (6)
Como debes saber:
(*operator int() const)(int, int)
{
return _funcPtr;
}
(Corregido. Otra vez.)
Actualización: Johannes Schraub y Luc Danton me informaron que esta sintaxis no es válida y que realmente debe usar typedef. Ya que dice que typedefs no son una opción, aquí hay una clase auxiliar que puede envolver su typedef:
template<typename R, typename A1, typename A2>
struct MakeFunctionType
{
typedef R(*type)(A1, A2);
};
template<typename R, typename A1, typename A2>
operator typename MakeFunctionType<R, A1, A2>::type () const
{
// implementation is unimportant here
}
He estado moliendo mi cabeza contra una idea que es lo suficientemente simple en mi cabeza, pero no puedo averiguar cómo implementar en C ++.
Normalmente, puedo declarar una clase con un operador de conversión como en este simple ejemplo:
class Foo
{
private:
int _i;
public:
Foo( int i ) : _i(i) { }
operator int( ) const
{
return i;
}
};
Así que ahora puedo escribir cosas impresionantes como
int i = Foo(3);
Pero en mi caso particular, me gustaría proporcionar un operador para convertir un objeto en un puntero de función (por ejemplo, convertir una instancia de Bar
en un puntero de función int(*)(int, int)
). Esto es lo que inicialmente intenté:
class Bar
{
private:
int (*_funcPtr)(int, int);
public:
Bar( int (*funcPtr)(int, int) ) : _funcPtr(funcPtr) { }
operator int(*)(int, int) ( ) const
{
return _funcPtr;
}
};
Pero la función del operador no se compila, con estos errores que se generan:
expected identifier before ''*'' token
''<invalid-operator>'' declared as a function returning a function
También he intentado variaciones simples sobre lo anterior, como rodear el tipo de retorno entre paréntesis, pero todas estas ideas también han fallado.
¿Alguien sabe cuál es la sintaxis para declarar un método de operador de puntero de conversión a función, o si es posible hacerlo?
Nota: Estoy compilando esto con Code :: Blocks usando GCC 4.5.2. Las respuestas relacionadas con algunos de los nuevos conceptos de C ++ 0x también son bienvenidas.
Editar
En mi esfuerzo por simplificar el ejemplo, sin querer omití un detalle. Es un poco raro, pero en lugar de devolver estrictamente un puntero int(*)(int,int)
, el operador de conversión está destinado a tener plantillas:
template<typename ReturnType, typename ArgType1, typename ArgType2>
operator ReturnType(*)(ArgType1, ArgType2) ( ) const
{
// implementation is unimportant here
}
Por lo que sé, ya no puedo tipear este tipo de letra. Esto claramente hace que las cosas sean mucho más torpes, pero espero que todavía haya un camino.
En C ++ 11, es posible usar una plantilla de alias para convertir a cualquier función, evitando la necesidad de struct
rasgos de tipo personalizado.
class Bar
{
private:
template<typename ReturnType, typename ArgType1, typename ArgType2>
using funcptr = ReturnType(*)(ArgType1, ArgType2);
public:
template<typename ReturnType, typename ArgType1, typename ArgType2>
operator funcptr<ReturnType, ArgType1, ArgType2> ( ) const;
};
Para limitar esto a solo int(*)(int, int)
, podemos usar SFINAE o static_assert
.
Los siguientes trabajos en GCC:
template<typename ReturnType, typename ArgType1, typename ArgType2>
operator decltype((ReturnType(*)(ArgType1, ArgType2)) nullptr)() const
{
// ...
}
Si desea que el código sea legible, debe utilizar un typedef. Ni siquiera uso punteros de funciones sin escribirlas, la sintaxis es demasiado horrible.
Gol:
template<typename ReturnType, typename ArgType1, typename ArgType2>
operator ReturnType(*)(ArgType1, ArgType2) ( ) const
{
return 0;
}
Camino:
// 1: helper structure
template <typename R, typename A0, typename A1>
struct helper {
typedef R (*type)(A0,A1);
};
// 2: operator
template <typename R, typename A0, typename A1>
operator typename helper<R, A0, A1>::type() const {
return 0;
}
¡Échale un vistazo a ideone !
Utilice un typedef. Es más fácil de leer, de todos modos:
class Bar
{
public:
typedef int (*fptr_t)(int, int);
Bar(fptr_t funcPtr) : _funcPtr(funcPtr) { }
operator fptr_t() const
{
return _funcPtr;
}
private:
fptr_t _funcPtr;
};
[editar]
Para el caso de su plantilla no veo cómo usar typedef. @Kerrik da la versión (desordenada) de la sintaxis que debería funcionar.
EDITAR:
Dado que su clase tiene un puntero de función no plantilla asignado en la construcción:
private:
int (*_funcPtr)(int, int);
No es posible convertirlo más tarde en un puntero de función de cualquier tipo.
Por lo tanto, asumiré que se refería a una sobrecarga de operador miembro de clase de plantilla, no a una sobrecarga de operador miembro de plantilla de clase
Versión de plantilla:
template<typename ReturnType, typename ArgType1, typename ArgType2>
class Bar {
public:
typedef ReturnType (*fptr_t)(ArgType1, ArgType2);
operator fptr_t ( ArgType1 arg1, ArgType2 arg2 ) const
{
// implementation is unimportant here
}
//etc...
};
Luego se usa así:
//create functor to some function called myfunc
Bar::fptr_t func_ptr = Bar<int, int, int>(&myfunc);
//call functor
int i = func_ptr(1,2);