Sintassi C ++ strana individuata nei parametri del modello Boost

Stavo dando un’occhiata alla documentazione della class “Funzione” in Boost, e ci siamo imbattuti in questo:

boost::function f; 

Devo ammettere che questa syntax è altamente confusa per me. Come può essere legale C ++?

C’è qualche trucco sotto il cofano? Questa syntax è documentata ovunque?

[Modifica] Questa è una risposta alla domanda originale e inedita dell’autore, che in realtà era composta da due domande.

Devo ammettere che questa syntax è altamente confusa per me. Come può essere legale C ++? 🙂 C’è qualche trucco sotto il cofano? Questa syntax è documentata ovunque?

Questo è perfettamente legale e in realtà non è troppo complicato.

 template  class C { public: T* function_pointer; }; void fn(int x) { cout << x << endl; } int main(int argc, char** argv) { C c; c.function_pointer = &fn; c.function_pointer(123); // outputs x } 

È fondamentalmente la stessa cosa che fare:

 typedef void Function(int); C c; 

Questo tipo non è solo C ++ applicabile, è altrettanto applicabile in C (il tipo C reale è parametrizzato a). Il modello magico qui sta prendendo qualcosa di simile alla funzione typedef qui e in grado di rilevare i tipi dei valori restituiti e degli argomenti. Spiegando che sarebbe troppo lungo qui e boost :: function utilizza molti dei meta-template di tratti di funzione in boost per recuperare tali informazioni. Se vuoi davvero passare il tempo per imparare questo, dovresti provare a capire l’implementazione del boost a partire da boost :: function_traits in Boost.Type Traits.

Tuttavia, voglio affrontare il tuo problema generale. Penso che tu stia tentando troppo per semplificare un paio di righe di codice perfettamente accettabile. Non c’è niente di sbagliato nel passare gli argomenti per le sottoclassi del comando attraverso i loro costruttori di sottoclassi parametrizzati. Vale veramente la pena tentare di coinvolgere le liste di caratteri e le soluzioni boost :: function come qui, aumentando così i tempi di compilazione e la complessità del codice in modo significativo, solo per quello?

Se vuoi ridurlo ulteriormente, scrivi semplicemente una funzione execute che eseguirà qualsiasi sottoclass di comandi e aggiungila allo stack di annullamento e così via:

 typedef boost::shared_ptr 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) ); 

Penso davvero che il compromesso di cercare di renderlo più complicato non vale la pena. Gli autori di boost volevano scrivere una soluzione estremamente generica per la funzione boost :: che sarebbe stata utilizzata da molte persone su molte piattaforms e compilatori. Tuttavia, non hanno tentato di generalizzare un sistema di comandi in grado di eseguire funzioni con firme diverse attraverso un sistema di annullamento unificato (richiedendo in tal modo che lo stato di questi comandi fosse preservato anche dopo aver inizialmente terminato di chiamarli ed essere in grado di annullare e ri -eseguirli senza specificare nuovamente i dati dello stato originale sulle esecuzioni successive). Per questo, il tuo approccio basato sull’eredità è molto probabilmente il migliore e più diretto.