Implementazione dell'interfaccia functor vs Funcion objects come membri C ++

0

Attualmente sto scrivendo un'implementazione della rete neurale in c ++ e mi è venuta una domanda curiosa:

Voglio che il mio NN sia "generico", quindi voglio essere in grado di definire le funzioni personalizzate di trasferimento e di errore. Il mio primo istinto è quello di creare un'interfaccia (classe astratta) e passare oggetti derivati come argomento (fondamentalmente functors):

class VectorizedFunction {
public:
    virtual MatrixXf  F(const Ref<MatrixXf>&) = 0;
    virtual MatrixXf dF(const Ref<MatrixXf>&) = 0;
    virtual ~VectorizedFunction() = 0;
}

class VTanh : public VectorizedFunction {
    MatrixXf  F(const Ref<MatrixXf>&){
        return M.array().tanh().matrix();
    }

    MatrixXf dF(const Ref<MatrixXf>&){
        auto th = M.array().tanh(); 
        return (1 - th*th).matrix();
    }
}

Ma poi mi sono ricordato che gli oggetti funzione sono stati introdotti in C ++ 11 permettendomi di fare cose come:

class VectorizedFunction {
public:
    function<MatrixXf(const Ref<MatrixXf>&)> F;
    function<MatrixXf(const Ref<MatrixXf>&)> dF;
};

VectorizedFunction tf;
tf.F = [&](const Ref<MatrixXf>& M)->MatrixXf { return M.array().tanh().matrix(); };
tf.dF = [&](const Ref<MatrixXf>& M)->MatrixXf { auto th = M.array().tanh(); return (1 - th*th).matrix(); };

Quale delle due opzioni produrrà meno overhead e quale sarà più facile da mantenere?

    
posta FanciestBanana 09.11.2017 - 11:54
fonte

1 risposta

2

Diamo un'occhiata ai pro e contro di un approccio basato sulle funzioni:

Pro:

  • Flessibilità - Non c'è assolutamente alcun dubbio in questo. Saranno chiamate tutte le funzioni che possono essere superate. Naturalmente derivando da una classe astratta come nel nostro altro caso è flessibile, obbligando anche chiunque desideri avere un comportamento personalizzato derivante da quella classe che è un piccolo limite. In breve, sono entrambi flessibili, ma questa soluzione è più difficile.
  • User-friendly - Se stai scrivendo una libreria, questo è favorevole a un design migliore in quanto consente all'utente della tua libreria di fare essenzialmente ciò che desidera piuttosto che obbligarlo a derivare da una classe specifica. Non un grosso grande di per sé, ma ho conosciuto molti programmatori che erano infastiditi da queste cose.

Contro

  • Manutenibilità - C'è assolutamente niente che lega VectorizedFunction alla sua implementazione. Questo non è solo un accoppiamento lento. La cosa sta penzolando sotto i tuoi piedi come un'appendice in più. Se trovi un bug, devi vedere come viene chiamato per sapere dove si trova la tua implementazione. Mentre nell'approccio di classe astratta, devi semplicemente controllare tutte le classi derivate da esso che possono essere trovate semplicemente cercando tutto il codice per VectorizedFunction .

In definitiva, è una tua decisione, ma se lo scrivessi per i miei scopi, rimango con l'approccio astratto alla classe. Altrimenti, penso che preferirei seguire l'approccio più flessibile. Spero che ti aiuti!

    
risposta data 09.11.2017 - 13:00
fonte

Leggi altre domande sui tag