mercredi 20 juillet 2016

Using varargs with templates

I'm working on a game with a simple "delegate" system.

Here is the source file (sorry for the french comments) :

#ifndef C_DELEGATE_HPP_
#define C_DELEGATE_HPP_


#include <list>
#include <functional>

#include <boost/function.hpp>


namespace ns
{


////////////////////////////////////////////////////////////////////////////////
/// Classe gérant une liste de callback. Les callbacks ont entre 0 et 1
/// arguments.
///
template <typename ... Args>
class C_Delegate
{

public:

    ////////////////////////////////////////////////////////////////////////////
    /// Type des callbacks.
    ///
    typedef std::function<void (Args...)> callback;




    ////////////////////////////////////////////////////////////////////////////
    /// Structure répresentant un callback.
    ///
    struct S_Callback
    {

        callback    callback_ptr;

        bool        once;

    }; // S_Callback




    ////////////////////////////////////////////////////////////////////////////
    /// Type pour la liste des callbacks.
    ///
    typedef std::list <S_Callback> callback_list;



public:

    ////////////////////////////////////////////////////////////////////////////
    /// Constructeur.
    ///
    C_Delegate (void)
    { }


    ////////////////////////////////////////////////////////////////////////////
    /// Destructeur.
    ///
    virtual ~C_Delegate (void) throw ()
    { }




    ////////////////////////////////////////////////////////////////////////////
    /// Connecte une fonction à la liste des callbacks.
    ///
    /// @param cb : Callback.
    /// @param instance : Instance de l'objet utilisant le callback.
    /// @param once : Détermine si le callback est appelé que une fois ou non.
    ///
    void connect (callback cb, bool once=false) throw ()
    {

        _callbacks.push_back ( {cb, once} );

    }


    ////////////////////////////////////////////////////////////////////////////
    /// Déconncte une fonction de la liste.
    ///
    /// @param cb : Callback.
    /// @param instance : Instance de l'objet utilisant le callback.
    ///
    void disconnect (callback cb) throw ()
    {
        for (auto i = _callbacks.begin(); i != _callbacks.end(); i++) {
            if (i->callback_ptr == cb) {
                _callbacks.erase(i);
                return;
            }
        }
    }




    ////////////////////////////////////////////////////////////////////////////
    /// Appels tous les callbacks lé à l'objet actuel.
    ///
    /// @param a1 : Argument à passer aux callbacks.
    ///
    void emit(Args... args) throw ()
    {
        for (auto i = _callbacks.begin(); i != _callbacks.end(); i++)
        {
            i->callback_ptr(args...);

            if (i->once)
                _callbacks.erase (i);
        }
    }



private:

    ////////////////////////////////////////////////////////////////////////////
    /// Liste des callbacks.
    ///
    callback_list   _callbacks;


}; // C_Delegate


} // namespace ns

#endif

The linter says nothing, good. But, using with C_Delegate<void> create this error : invalid parameter type 'void'.

How can I make my C_Delegate::emit method to allow using no parameter callback ?

Thanks for your answers !

Aucun commentaire:

Enregistrer un commentaire