2010-06-27 10 views
8

que estaba teniendo un vistazo a la documentación de la clase "Función" en Impulso, y se topó con esto:C++ extraña sintaxis visto en la plantilla Boost parámetros

boost::function<float (int x, int y)> f; 

debo admitir esta sintaxis es muy confuso para mí. ¿Cómo puede ser esto legal C++?

¿Hay algún truco debajo del capó? ¿Esta sintaxis está documentada en alguna parte?

+0

Haga solo una pregunta por pregunta. Si tiene dos preguntas para formular, envíe dos preguntas por separado. – bdonlan

+0

Es cierto, lo siento, no lo volveré a hacer – Dinaiz

+0

Puede editar su pregunta para eliminar una de las preguntas y dividirla en otra pregunta; es difícil responder así porque si alguien solo conoce la respuesta a una de sus preguntas , se sentirán reacios a enviar una respuesta. – bdonlan

Respuesta

9

[Editar] Esta es una respuesta a la pregunta original no editada del autor, que en realidad eran dos preguntas.

Debo admitir que esta sintaxis es muy confusa para mí. ¿Cómo puede ser esto legal C++? :) ¿Hay algún truco debajo del capó? ¿Está documentada esta sintaxis en algún lugar?

Esto es perfectamente legal y en realidad no es demasiado complicado.

template <class T> 
class C 
{ 
public: 
    T* function_pointer; 
}; 

void fn(int x) 
{ 
    cout << x << endl; 
} 

int main(int argc, char** argv) 
{ 
    C<void (int x)> c; 
    c.function_pointer = &fn; 
    c.function_pointer(123); // outputs x 
} 

Es básicamente lo mismo que hacer:

typedef void Function(int); 
C<Function> c; 

Este tipo no es sólo aplicable C++, que es igual de aplicable en C (el tipo real C es parametrizada a). La magia de la plantilla aquí es tomar algo como la función typedef aquí y ser capaz de detectar los tipos de los valores de retorno y argumentos. Explicar que sería demasiado extenso aquí y la función boost :: usa muchas de las meta-plantillas de rasgos de función en potencia para recuperar esa información. Si realmente quieres pasar el tiempo para aprender esto, debes tratar de comprender la implementación de impulso que comienza con boost :: function_traits en Boost.Type Traits.

Sin embargo, quiero abordar su problema general. Creo que estás intentando simplificar un par de líneas de código perfectamente aceptable. No hay nada de malo en pasar los argumentos para sus subclases de comando a través de sus constructores parametrizados de subclase. ¿De verdad vale la pena tratar de incluir listas de tipos y soluciones boost :: function-like aquí, aumentando así los tiempos de compilación y la complejidad del código significativamente, solo por eso?

Si desea reducir aún más, acaba de escribir una función que se ejecutará cualquier subclase de comandos y añadirlo a la pila de deshacer y así sucesivamente ejecutar:

typedef boost::shared_ptr<Command> CommandPtr; 

void execute(const CommandPtr& cmd) 
{ 
    cmd->execute(); 
    // add command to undo stack or whatever else you want to do 
} 

// The client can simply write something like this: 
execute(CommandPtr(new CmdAdd(some_value)); 

Realmente creo la disyuntiva de intentar hacerlo más complicado no vale la pena. Los autores del impulso querían escribir una solución de propósito general para la función boost :: que sería utilizada por muchas personas en muchas plataformas y compiladores. Sin embargo, no intentaron generalizar un sistema de comando capaz de ejecutar funciones con diferentes firmas a través de un sistema de deshacer unificado (lo que requiere que se conserve el estado de estos comandos incluso después de que uno haya terminado de llamarlos y pueda deshacer y re -ejecutarlos sin volver a especificar los datos de estado originales en las ejecuciones posteriores). Para eso, su enfoque basado en la herencia es probablemente el mejor y más directo.

+2

'typedef float (int, int) Command', lamento decir que no es legal C. El código C correcto sería' typedef float Command (int, int) '. 'typedef' toma una declaración regular, y en lugar de definir el objeto nombrado (es decir, función o variable), usa el nombre como alias para el tipo de tipo del objeto. –

+0

+1 Gran respuesta – fingerprint211b

+0

@Dale Disculpas, tienes razón y eso también es ilegal en C++. Ese fue un error apresurado al tratar de explicar para qué C se parametrizó con C c; Es el equivalente a escribir: typedef float Command (int, int); C c. Lo edité para corregir el error. – stinky472

Cuestiones relacionadas