IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

Faire un wrapper sur une fonction de callback.


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Invité
    Invité(e)
    Par défaut Faire un wrapper sur une fonction de callback.
    Salut, trouvant les wrapper vraiment très pratique, j'ai décidé d'en faire quelque un dans mon framework à l'aide de la méta-programmation.

    Mais je bloque ici (encore à cause de la redéfinition de fonctions template) mais cette fois-ci mes template sont des pointeurs sur fonction, j'ai crée une factory qui se charge d'instancier différent wrapper sur différent type de wrapper sur mes différent type de foncteurs.

    Bref voici le code de ma factory :
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
     
    template <> class FastDelegate<DefaultVoid> {
        public :
        FastDelegate () {
            delegate = nullptr;
        }
     
        bool operator!() {
            return delegate == nullptr;
        }
        template <typename O, typename F, typename ...A> FastDelegate(F f, O* object, A... args) {
            delegate = new FastDelegate7<F, O, A...>(f, object, args...);
        }
        template <typename F, typename ...A> FastDelegate(F f, A... args) {
            delegate = new FastDelegate6<F, A...>(f, args...);
        }
        template <typename O, typename ...A> FastDelegate(void(O::*f)(A...), O* object, A... args) {
            delegate = new FastDelegate2<O, A...>(f, object, args...);
     
        }
        template <typename O, typename ...A> FastDelegate(void(O::*f)(A...) const, O* object,  A... args) {
            delegate = new FastDelegate2<O, A...>(f, object, args...);
        }
        template <typename O, typename D, typename ...A> FastDelegate(D* derived, A... args) {
            if (static_cast<O*>(derived)) {
                static_cast<FastDelegate2<O, A...>*>(delegate)->setParams(static_cast<O*>(derived), args...);
            }
        }
        template <typename ...A> FastDelegate(void(*f)(A...), A... args) {
            delegate = new FastDelegate0<A...>(f, args...);
        }
        void operator()() {
            (*delegate)();
        }
        template <typename F, typename O, typename... A> void setFuncParams(O* object, A... args) {
            if (static_cast<FastDelegate6<F, O, A...>*>(delegate)) {
                static_cast<FastDelegate6<F, O, A...>*>(delegate)->setParams(object, args...);
            }
        }
        template <typename F, typename... A> void setFuncParams(A... args) {
            if (static_cast<FastDelegate7<F, A...>*>(delegate)) {
                static_cast<FastDelegate7<F, A...>*>(delegate)->setParams(args...);
            }
        }
        template <typename O, typename ...A> void setParams(O* object, A... args) {
            if (static_cast<FastDelegate2<O, A...>*>(delegate)) {
                static_cast<FastDelegate2<O, A...>*>(delegate)->setParams(object, args...);
            }
        }
        template <typename O, typename D, typename ...A> void setParams(D* derived, A... args) {
            if (static_cast<O*>(derived)) {
                static_cast<FastDelegate2<O, A...>*>(delegate)->setParams(static_cast<O*>(derived), args...);
            }
        }
        template<typename ...A> void setParams(A... args) {
            if (static_cast<FastDelegate0<A...>*>(delegate)) {
                static_cast<FastDelegate0<A...>*>(delegate)->setParams(args...);
            }
        }
        bool operator==(FastDelegate &other) {
            return delegate == other.delegate;
        }
        private :
        Delegate* delegate;
    };

    Et je voudrais arriver à quelque chose comme ceci :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    class AClass {
        public :
        void aMemberFunction(std::string arg) {
            std::cout<<"a member function with argument : "<<arg<<std::endl;
        }
        int aMemberFunctionWithReturn(std::string arg) {
            std::cout<<"a member function with argument : "<<arg<<std::endl;
            return 1;
        }
    };
    void aFunction (std::string arg) {
        std::cout<<"a function with argument : "<<arg<<std::endl;
    }
    int aFunctionWithReturn (std::string arg) {
        std::cout<<"a function with argument : "<<arg<<std::endl;
        return 1;
    }
    int main(int argc, char* args[])
    {
       odfaeg::FastDelegate<void> anonymFunc([&](){std::cout<<"Coucou!"<<std::endl;});
        anonymFunc();
        odfaeg::FastDelegate<void> func(&aFunction, "arg1");
        func();
        odfaeg::FastDelegate<int> funcWithRet(&aFunctionWithReturn, "arg1");
        int r = funcWithRet();
        std::cout<<"return : "<<r<<std::endl;
        AClass anObj;
        odfaeg::FastDelegate<void> aMemberFunc(&AClass::aMemberFunction, &anObj, "arg1");
        aMemberFunc();
        return 0;
    }

    Pas de soucis pour les fonctions non membre par contre j'ai une erreur en compilation pour les fonctions membre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    ||=== Build: Debug in ODFAEG-DEMO (compiler: GNU GCC Compiler) ===|
    /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|64|warning: "/*" within comment [-Wcomment]|
    /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|99|warning: "/*" within comment [-Wcomment]|
    /usr/local/include/odfaeg/Core/signal.h||In instantiation of ‘R odfaeg::callback(F, A ...) [with R = void; F = void (AClass::*)(std::basic_string<char>); A = {AClass*, const char*}]’:|
    /usr/local/include/odfaeg/Core/signal.h|30|required from ‘odfaeg::FastDelegate7<F, O, A>::FastDelegate7(F, O*, A ...) [with F = void (AClass::*)(std::basic_string<char>); O = AClass; A = {const char*}]’|
    /usr/local/include/odfaeg/Core/signal.h|413|required from ‘odfaeg::FastDelegate<void>::FastDelegate(F, O*, A ...) [with O = AClass; F = void (AClass::*)(std::basic_string<char>); A = {const char*}]’|
    /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|123|required from here|
    /usr/local/include/odfaeg/Core/signal.h|9|error: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘func (...)’, e.g. ‘(... ->* func) (...)’|
    /usr/local/include/odfaeg/Core/signal.h|9|error: return-statement with a value, in function returning 'void' [-fpermissive]|
    ||=== Build failed: 2 error(s), 6 warning(s) (0 minute(s), 2 second(s)) ===|
    Le problème est qu'il me choisi le mauvais constructeur, il choisi celui pour créer le wrapper sur la fonction anonyme hors que ce n'est pas une fonction anonyme mais une fonction membre.

    J'ai bien essayé quelque chose comme ça mais cela ne marche pas :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    template <typename F, typename ...A, typename T, class = typename std::enable_if<!std::is_member_function_pointer<F>::value>::type> FastDelegate(F f, A... args, T) {
            delegate = new FastDelegate6<F, A...>(f, args...);
        }

    C'est alors lorsque je veux construire le pointeur sur la fonction anonyme que ça ne marche plus, et je ne vois pas très bien comment procéder pour que le compilateur me choisisse le bon constructeur.

    Merci d'avance pour vos réponses.

  2. #2
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 760
    Par défaut
    D'après ton prototype, il faut que les arguments envoyés au constructeur soient de même type que les paramètres de la fonction membre. Les strings littérales sont des tableaux de caractère constant et non des std::string.

    Mais pourquoi ne pas utiliser std::function ?

  3. #3
    Invité
    Invité(e)
    Par défaut
    Tu veux dire quelque chose comme ça ?

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    std::function<F> func = &myFunc;

    C'est vrai que j'aurai pu mais bon dans se cas lors de setParam je doit indiquer en paramètre template que c'est une std::function hors que si j'utilise un pointeur de fonction classique le compilateur peut me déduire automatiquement le type de la fonction.
    Avec un std::function je dois savoir que c'est une std::function de type void(std::string) lorsque je veux changer la valeur des arguments de la fonction.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    delegate.setParams<std::function<void(std::string)>>("argument");
    Hors que avec un pointeur de fonction classique ceci suffit : delegate.setParams("argument");.
    L'écriture est donc plus simple.
    Et bon autant changer la valeur des paramètres du pointeur de la fonction avec un tuple plutôt que avec std::bind avec les placeholders ou je suis obligé de déclarer et utiliser la fonction dans le même bloc. --'
    C'est pas vraiment ce que je veux, moi je veux pouvoir accéder au pointeur de fonction n'importe ou dans le programme


    C'est bizarre car dans un autre fichier j'ai fais la même chose mais je n'ai pas ce problème de compilation.
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    odfaeg::Command moveAction(combined, odfaeg::FastDelegate<void>(&MyAppli::keyHeldDown, this, sf::Keyboard::Unknown));
            odfaeg::InputSystem::getListener().connect("MoveAction", moveAction);
            odfaeg::g2d::AmbientLight::getAmbientLight()->setColor(sf::Color(0, 0, 255));
            odfaeg::Command mouseInsideAction(odfaeg::FastDelegate<bool>(&MyAppli::mouseInside,this, sf::Vector2f(-1, -1)), odfaeg::FastDelegate<void>(&MyAppli::onMouseInside, this, sf::Vector2f(-1,-1)));
            odfaeg::InputSystem::getListener().connect("MouseInside",mouseInsideAction);
            odfaeg::Command leftMouseButtonPressedAction (a5, odfaeg::FastDelegate<void>(&MyAppli::leftMouseButtonPressed, this, sf::Vector2f(-1, -1)));
            odfaeg::InputSystem::getListener().connect("LeftMouseButtonPressedAction", leftMouseButtonPressedAction);
    Dernière modification par Invité ; 16/08/2014 à 17h03. Motif: Ajout des balises [codeinline]

Discussions similaires

  1. Réponses: 1
    Dernier message: 07/03/2013, 10h47
  2. Réponses: 5
    Dernier message: 18/11/2007, 01h15
  3. Probleme de pointeur sur une fonction
    Par nicky78 dans le forum C
    Réponses: 2
    Dernier message: 23/05/2004, 20h26
  4. Erreur sur une fonction avec des paramètres
    Par Elois dans le forum PostgreSQL
    Réponses: 2
    Dernier message: 05/05/2004, 21h00
  5. PerlDoc sur une fonction d'un module
    Par lesouriciergris dans le forum Modules
    Réponses: 2
    Dernier message: 13/03/2003, 20h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo