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 :

Quelques questions à propos du langage lui même.


Sujet :

Langage C++

  1. #21
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Mon code est complet (dans le cas retour void), tu n'as pas besoin de rajouter de constructeur. Voir l'exemple f4 que j'ai donné. Et si ca crash, dis le à la place de considérer qu'il est de facto non viable.

    NB: Bien prendre la dernière version que j'ai donné, je suis pas chez moi pour tester avec le morceau de code que tu donnes, je le ferais ce soir.

    PS: J'ai pour habitude de tester l'ensemble des codes que je propose avec clang et un haut niveau de warning. Si ca ne marche pas c'est que je suis dans une UB sans faire exprès ou que j'utilise une feature que les compilateurs n'implementent pas tous parfaitement.

  2. #22
    Invité
    Invité(e)
    Par défaut
    Ok désolé prochaine fois je le dirai direct quand ça crash.

    J'aimerais en effet faire une classe qui réunisse tout les wrappers.

    C'est pour ça que j'ai fais 5 constructeurs à la base :
    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
     
    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...);
        }

    Ce qui est quand même beaucoup.
    J'ai essayer de réduire donc et de ne faire que 2 constructeurs : (1 pour faire le wrapper dynamique, et un autre pour le wrapper statique.)

    J'ai remplacer donc le foncteur dans FastDelegate6 par un std::function exactement comme tu as fais.

    Malheureusement c'est dès que j'ai fais ça que ça a commencer à crasher. (Pour le wrapper dynamique uniquement)

    Mais ça m'a l'air un peu caste tête tout ça je me demande si je ne ferais pas mieux de garder mon code actuel.

    Au passage j'utilise gcc comme compilateur c'est peut être pour ça.

  3. #23
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Donc tu veux intégrer systématique le système que j'ai nommé make_dynamic dans FastDelegate ? Pour ce faire je te propose une approche à mi-chemin entre ce que tu faisais avec ton Functor et ce que je te propose.

    L'idée est de faire un DynamicFunction qui intègre le make_dynamic, en gros le comportement est le même que std::function sauf dans le cas d'un pointeur sur fonction membre où il intègre un dynamic_cast en plus.

    Ensuite tu reprends le code que je t'ai donné et tu remplaces le type std::function par un paramètre template et tu rajoutes ce paramètre dans les paramètres template de la classe en mettant une valeur par défaut sur ton DynamicFunction ou sur std::function.

    L'enchainement du raisonnement est le suivant : j'ai besoin d'un type-erasure sur les foncteurs, j'utilise std::function, j'ai besoin de dynamic_cast automatiquement dans certain cas, j'embarque std::function auquel j'assigne un foncteur englobant dans le cas où j'ai besoin de dynamic_cast, j'ai besoin de type-erasure sur les paramètres, je l'implémente par dessus.

    J'essaierais de te proposer quelque chose qui va dans ce sens en fin de journée, même si je considère que c'est une erreur. Si j'enregistre une fonction membre avec la classe fille et que je fait un appel avec la classe mère, je m'attends à une erreur, pas à un dynamic_cast automatique.

    NB: Tu devrais d'ailleurs clarifier ta politique en de retour nullptr des dynamic_cast : ne rien faire ou lancer une exception ?

    PS: Si tu connais la notion, std::function ou DynamicFunction devient classe de politique de FastDelegate.

    Edit: Ou bien une fonction de création que selon le cas donne directement un std::function ou passe par une enveloppe intermédiaire qui fait le dynamic_cast avant de retourner le std::function. Dans ce cas on se retrouve avec un outil qui s'apparente (syntaximent) aux allocateurs utilisé dans les conteneurs. A voir ce qui est le plus simple à mettre en place.

  4. #24
    Invité
    Invité(e)
    Par défaut
    Oui je voudrais lancer une exception si le dynamic_cast échoue.

    Il me faudrait en effet un exemple de code car là j'ai un crash lorsque j'essaye d'utiliser un std::function dans ma classe FastDelegate6, faudrait une classe qui me dise genre "si la classe du pointeur sur fonction membre est une classe fille et que le type de l'objet sur lequel invoquer le pointeur de fonction est une classe mère, alors, utilise DynamicFunction, sinon, utilise std::function.

    Mais je ne vois pas très bien comment faire ça.

    Tu parles d'un truc du genre ?
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    template <typename D, typename B, typename...A> 
    DynamicDelegate {
         //Ta classe
         std::tuple<B, A...> params;
         void(D::*f)(B, A...)
    };
    template <typename... A>
    Delegate <A...> {
        //Ta classe
        std::tuple<A...>
        std::function<void(A...)> function;
    }

    Mais je ne vois pas comment choisir entre l'un ou l'autre ici j'ai essayé ça :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    template <typename F, typename A...>
    FastDelegate(F&& f, A&&... args) {
        //Non dynamic version.
    }
    template <typename D,  typename B, typename A...>
    FastDelegate(void(D::*)(B*, A...), B* base, A&&... args) {
       //Dynamic version.
    }

    Mais ça crash lors de l'appel de la fonction. :/

    PS : j'ai besoin d'un type erasure dans les deux cas hein.
    C'est pour ça que j'utilise pas std::function, c'est trop compliqué à faire sinon.

  5. #25
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Je ne comprends pas ce que tu fais encore avec ton FastDelegate6. Je ne l'ai pas dans le code que je propose, je ne comprends pas pourquoi tu l'as encore. Part du code que je propose (directement en copier/coller dans un nouveau projet) et test le. Quand c'est fait, continue dans ce nouveau projet pour intégrer directement make_dynamic dans FastDelegate en suivant les pistes que je propose dans mon dernier message.

    PS: Je considère toujours et je le redirais à chaque message, qu'intégrer le dynamic_cast systématiquement est une erreur.

  6. #26
    Invité
    Invité(e)
    Par défaut
    Ouais j'aurai pu aussi faire autrement, en redéfinissant les opérateur << et >> dans les classes dérivée genre un truc comme ceci :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    class OTextArchive {
          template <typename O>
          friend std::ostream& operator<<(std::ostream& out, O& object) {
                   out<<object;
                   return out;
          }
    };
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    class Base {
         virtual std::ostream& operator<<(std::ostream& out) {
                //Serialize everything here.
         }
    }
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    class Derived : public Base {
         virtual std::ostream& operator<<(std::ostream& out) {
                out<<Base::operator<<(out);
                //Serialize everything here.
        }
    }

    Plutôt que une fonction template, une factory et un delegate.

    Mais m'étant inspiré de boost à la base, j'ai voulu faire un truc similaire, c'était peut être pas la manière la plus simple de faire mais je me suis dis boost doit avoir ses raisons de faire ça comme ça, après réflexion j'aurai pu utiliser l'autre méthode et me passer de l'intégration d'un dynamic cast systématique.

    De plus certains langages comme le C# implémentent des delegates, et le conseille même afin d'éviter un crash au cas ou on appellerait un pointeur de fonction d'une classe fille sur un pointeur d'un objet d'une classe mère en lançant une exception à la place du crash.

  7. #27
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Mais boost fait complexe parce qu'il correspond à de nombreux cas d'utilisations.
    Il se donne de la sursouplesse pour permettre tout et n'importe quoi.

    Toi, tu vises un format d'archive précis, donc tu peux simplifier.

    Et faire "comme dans tel autre langage" est un bon moyen d'écrire du code de mauvaise qualité.
    Quels que soient les langages écrits ou mimés.


    Et puis, quitte à faire "comme boost", prends boost.serialization. Comme elle est header-only, tu peux la copier dans ton projet.
    Je pense que tu perds du temps à refaire ce qui existe déjà.

    Sauf si tu considère le côté apprentissage. Auquel cas, tu n'es pas particulièrement sur la bonne voie, au vu des trésors de langage utilisés.

    PS: Et puis, éventuellement essaie de poursuivre tes discussions, pour le même sujet réel, tu es déjà à 22 sujets ouverts, en à peine plus d'un mois.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  8. #28
    Invité
    Invité(e)
    Par défaut
    Bon finalement j'ai changé un peu le code suivant mes principes de codage :

    -La classe FastDelegate renvoie une exception si le type de la classe du pointeur sur la fonction membre et le type de l'objet sur lequel est appelé le pointeur sur la fonction membre ne sont pas polymorphique.

    -Une fonction anonyme ne peut pas capturer de variables et la fonction ne peut prendre des paramètres que lorsqu'elle est déclarée, impossible de changer les paramètres de la fonction anonyme une fois qu'elle est déclarée. (Après tout une fonction anonyme en général on l'utilise quand on a besoin de l'appeler qu'une seule fois ou bien plusieurs fois mais toujours avec les même paramètres.)
    Du coup plus de problèmes avec la déduction de template sur la fonction anonyme lorsque je veux en changer les paramètres et j'ai toujours trouvé que c'était pas pratique et qu'il valait mieux utiliser une fonction non anonyme dans ce cas la.

    -La classe factory lancera une exception si la fonction template virtuelle ou bien le type sur lequel on veut appelé la fonction template virtuelle n'est pas enregistré dans la factory.

    Voila je pense que comme ça c'est mieux, désolé j'ai essayer d'intégré ton code dans mon projet mais je n'y suis pas arrivé, une fois que je dois faire un dynamic_cast systématiquement, ça crash. (Je pense que le compilateur ne me fait pas la distinction entre une fonction membre et une std::function dans ces cas là) :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    template <typename F, typename... A>
    FastDelegate<F&&, A...>
    template <typename O, typename... A>
    FastDelegate<void(O::*)(A...)>

    Il me considère que la fonction membre c'est F et non pas void(O::*)(A...) ce qui peut expliquer le crash.

    Je ne pense pas qu'il y ai vraiment un autre moyen donc sans utiliser un wrapper personnel pour lever cette ambiguité.

  9. #29
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Si, inverser l'ordre des déclarations.
    Parce que l'ordre compte dans la résolution des templates.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  10. #30
    Invité
    Invité(e)
    Par défaut
    Ha ok donc tu veu dire dans mon cas, passer d'abord les paramètres et ensuite le pointeur de fonction dans l'une des deux fonctions ?

    Ok je vais essayer ça j'espère que ça ne crahsera plus.

  11. #31
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Je pensais plus à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    template <typename O, typename... A>
    FastDelegate<void(O::*)(A...)>
    template <typename F, typename... A>
    FastDelegate<F&&, A...>
    pour que la version membre soit détectée en premier.

    Tu es sûr que tu sais ce que tu fais?
    Tu devrais faire des petits projets, pour valider chaque brique de ton gros projet.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  12. #32
    Invité
    Invité(e)
    Par défaut
    Oui je sais ce que je fais maintenant j'essaye juste de faire en sorte que le compilateur puisse déduire le maximum de template possible et aussi essayer de réduire le volume du code source dans certains fichiers.

    Je suis plutôt en phase de nettoyage la.

    Bref j'ai encore un soucis pour stocker des références dans le tuple... (ou des constantes) mais, bon, à part ça, sa marche bien.

  13. #33
    Invité
    Invité(e)
    Par défaut
    Bon c'est pas le problème dont je pensais, c'est pas qu'il confond les fonctions, le cast marche bien, c'est avec la factory que ça merde dès que j'utilise une std::function et je ne sais pas pourquoi. :o

    Hors que avec ma propre implémentation je n'ai pas de crash.

  14. #34
    Invité
    Invité(e)
    Par défaut
    Re, je pense que je vais laisser ça comme ça :

    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
     
    class Foo {
        public :
        void bar(const int arg) {
            std::cout<<"bar : "<<arg<<std::endl;
        }
    };
    class Bar : public Foo {
        public :
        void bar (const int arg)   {
            std::cout<<"bar : "<<arg<<std::endl;
        }
    };
    void bar (const std::string& arg) {
        std::cout<<"bar : "<<arg<<std::endl;
    }
    int main(int argc, char* args[])
    {
        odfaeg::FastDelegate<void> freeFunction(&bar, "5");
        freeFunction();
        Foo* obj = new Bar();
        Bar bar;
        odfaeg::FastDelegate<void> memberFunctionDelegate (&Bar::bar, &bar, 10);
        memberFunctionDelegate.setParams(obj, 10);
        memberFunctionDelegate();
        odfaeg::FastDelegate<void> anonymousFunction([](int arg){std::cout<<"anonymous : "<<arg<<std::endl;}, 15);
        anonymousFunction.setParams<std::function<void(int)>>(20);
        anonymousFunction();
    }

    Le seul soucis étant que j'utilise une std::string ici :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    class Bar : public Foo {
        public :
        void bar (const std::string arg)   {
            std::cout<<"bar : "<<arg<<std::endl;
        }
    };
    class Bar : public Foo {
        public :
        void bar (const int arg)   {
            std::cout<<"bar : "<<arg<<std::endl;
        }
    };

    Il ne comprend plus rien.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    ||=== Build: Debug in ODFAEG-DEMO (compiler: GNU GCC Compiler) ===|
    /usr/local/include/odfaeg/Core/fastDelegate.h||In instantiation of ‘R odfaeg::callback(F, A ...) [with R = void; F = void (Bar::*)(std::basic_string<char>); A = {Bar*, const char*}]’:|
    /usr/local/include/odfaeg/Core/fastDelegate.h|30|required from ‘odfaeg::FastDelegate6<F, A>::FastDelegate6(F, A ...) [with F = void (Bar::*)(std::basic_string<char>); A = {Bar*, const char*}]’|
    /usr/local/include/odfaeg/Core/fastDelegate.h|321|required from ‘odfaeg::FastDelegate<void>::FastDelegate(F, A ...) [with F = void (Bar::*)(std::basic_string<char>); A = {Bar*, const char*}]’|
    /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|71|required from here|
    /usr/local/include/odfaeg/Core/fastDelegate.h|9|error: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘func (...)’, e.g. ‘(... ->* func) (...)’|
    /usr/local/include/odfaeg/Core/fastDelegate.h|9|error: return-statement with a value, in function returning 'void' [-fpermissive]|
    ||=== Build failed: 2 error(s), 4 warning(s) (0 minute(s), 3 second(s)) ===|
    Je pense que comme je stocke l'objet dans le tuple pour l'appelé ensuite avec le foncteur, et que les autres arguments ne sont pas des pointeurs, gcc râle car il pense que std::string est un objet.

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    private :
            std::tuple<O*, A...> params;
            Functor<R(MemberFunction<R(O*, A...)>, O*,  A...)> *funct;
            void* ret;

    Mmmm..., peut être en isloant l'objet il ne râlera plus mais bon comme je dois le passer à mon foncteur pour qu'il appelle le pointeur de fonction sur l'objet ça ne va pas être simple. :/

  15. #35
    Invité
    Invité(e)
    Par défaut
    Non Peu importe ce que je fait, il me choisi toujours la mauvaise fonction

    /usr/local/include/odfaeg/Core/fastDelegate.h||In instantiation of ‘R odfaeg::callback(F, A ...) [with R = void; F = void (Bar::*)(std::basic_string<char>); A = {Bar*, const char*}]’

    Peut importe dans quel ordre je les déclarer, et il ne me déduis pas celle-ci :o

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     template <typename O, typename ...A> FastDelegate(void(O::*f)(A...), O* object, A... args) {
            delegate = new FastDelegate2<O, A...>(f, object, args...);
     
        }

    Qui pourtant devrait être celle que le compilateur devrait choisir.

  16. #36
    Invité
    Invité(e)
    Par défaut
    Ha, apparemment c'est parce que se sont des cont char* et pas des std::string les chaînes entre "".

    J'ai changer le prototype des mes fonctions en const char* et ça marche.

    Mais comment je pourrai faire en sorte qu'il convertisse automatiquement les const char* en std::string ?

  17. #37
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Alors :
    Code : 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
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
     
    namespace odfaeg {
     
    template<class C, class... ArgT>
    struct DynamicWrapper {
    	DynamicWrapper(void (C::*pf)(ArgT...)) : pfunc(pf){}
    	template<class O, class... ArgU>
    	void operator()(O* o, ArgU&&... arg) const
    	{
    		if(dynamic_cast<C*>(o))
    			(dynamic_cast<C*>(o)->*pfunc)(std::forward<ArgU>(arg)...);
    	}
    private:
    	void (C::*pfunc)(ArgT...);
    };
     
    template<class F>
    class DynamicFunction;
     
    template<class... ArgT>
    class DynamicFunction<void(ArgT...)>
    	: std::function<void(ArgT...)>
    {
    	using Base = std::function<void(ArgT...)>;
     
    public:
    	template<class F>
    	DynamicFunction(F&& f) : Base(std::forward<F>(f))
    	{}
    	template<class C, class... ArgU>
    	DynamicFunction(void (C::*pf)(ArgU...))
    		: Base(DynamicWrapper<C,ArgU...>(pf))
    	{}
     
    	using Base::operator();
    };
     
    struct Delegate {
    	Delegate() =default;
    	virtual std::unique_ptr<Delegate> clone() const = 0;
    	virtual void operator()() const = 0;
    	virtual ~Delegate();
    protected:
    	Delegate(const Delegate&){}
    	Delegate& operator=(const Delegate&)
    	{ return *this; }
    };
     
    Delegate::~Delegate(){}
     
    template<class... ArgT>
    struct FastDelegateImpl : Delegate {
    	template<class F, class... ArgU>
    	FastDelegateImpl(F&& f, ArgU&&... arg)
    		: func(std::forward<F>(f))
    		, param(std::forward<ArgU>(arg)...)
    	{}
    	std::unique_ptr<Delegate> clone() const
    	{ return std::make_unique<FastDelegateImpl>(*this); }
    	void operator()() const
    	{ call(std::make_index_sequence<sizeof...(ArgT)>()); }
    	template<class... ArgU>
    	void setParam(ArgU&&... arg)
    	{ param=std::make_tuple(std::forward<ArgU>(arg)...); }
     
    private:
    	template<std::size_t... I>
    	void call(std::index_sequence<I...>) const
    	{ func(std::get<I>(param)...); }
     
    	DynamicFunction<void(ArgT...)> func;
    	std::tuple<ArgT...> param;
    };
     
    struct FastDelegate {
    	template<class F, class... Arg>
    	FastDelegate(F&& f, Arg&&... arg) :
    		delegate(std::make_unique<FastDelegateImpl<Arg...>>
    			(std::forward<F>(f),std::forward<Arg>(arg)...)
    		)
    	{}
    	FastDelegate(FastDelegate& rhs) : delegate(rhs.delegate->clone())
    	{}
    	FastDelegate(const FastDelegate& rhs) : delegate(rhs.delegate->clone())
    	{}
    	FastDelegate(FastDelegate&& rhs) =default;
    	FastDelegate& operator=(const FastDelegate& rhs)
    	{ return operator=(FastDelegate(rhs)); }
    	FastDelegate& operator=(FastDelegate&&) =default;
    	void operator()() const
    	{ (*delegate)(); }
    	template<class... Arg>
    	void setParam(Arg&&... arg)
    	{
    		using DynamicType = FastDelegateImpl<Arg...>*;
     
    		if(dynamic_cast<DynamicType>(delegate.get()))
    			dynamic_cast<DynamicType>(delegate.get())->setParam(std::forward<Arg>(arg)...);
    	}
    	void boo(){}
     
    private:
    	std::unique_ptr<Delegate> delegate;
    };
     
    }
    Pour ce que je proposais. Ensuite pour passer en classe de politique, il faut passer par une méta-fonction pour bien faire, or j'ai aucune envie de le faire sans utiliser boost.mpl. Utilisation :
    Code : 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
    66
    67
    68
     
    void foo(int i, int j)
    { std::cout << i << j; }
     
    struct A {
    	void bar(int i)
    	{ std::cout << i; }
    };
     
    struct B {
    	virtual void foo()
    	{ std::cout << 1; }
    	virtual ~B();
    };
     
    B::~B(){}
     
    struct C : B { void foo(); };
     
    void C::foo(){ std::cout << 2; }
     
    int main(){
    	odfaeg::FastDelegate f1(foo,3,4);
    	f1();
    	f1.setParam(5,6);
    	f1();
    	std::cout << std::endl;
     
    	odfaeg::FastDelegate f2(
    		[](int i, int j){ std::cout << i << j; },
    		7,8
    	);
    	f2();
    	f2.setParam(9,10);
    	f2();
    	std::cout << std::endl;
     
    	int i = 11;
    	odfaeg::FastDelegate f3(
    		[i](int j){ std::cout << i << j; },
    		12
    	);
    	f3();
    	f3.setParam(13);
    	f3();
    	std::cout << std::endl;
     
    	A a;
    	odfaeg::FastDelegate f4(&A::bar,&a,14);
    	f4();
    	f4.setParam(&a,15);
    	f4();
    	std::cout << std::endl;
     
    	odfaeg::FastDelegate f5 = f1;
    	f5();
    	f5=f3;
    	f5();
    	std::cout << std::endl;
     
    	C c;
    	B* b = &c;
    	odfaeg::FastDelegate f6(&C::foo,b);
    	f6();
    	f6.setParam(&c);
    	f6();
    	std::cout << std::endl;
    }
    A priori il ne manque aucun cas (je ne suis pas à l'abri d'un oubli ceci dit), je vais regarder les codes que tu mentionnais avant et ton dépôt pour voir si ça colle.(un peu la flemme à dire vrai, si tu trouves un cas qui ne marche pas, donne le code ici que je puis le copier/coller et te proposer une solution)

    NB: Code testé sous clang 3.4.2 (presque -Weverything et -Werror) et gcc 4.9.1 (-Wall et -Werror).

  18. #38
    Invité
    Invité(e)
    Par défaut
    Je vais paraître bête mais c'est quoi que tu appelles une méta fonction ?

  19. #39
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311

  20. #40
    Invité
    Invité(e)
    Par défaut
    Ok je vais essayer ton code et voir ce que je peux faire pour passer ça en classe de politique.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 12
    Dernier message: 13/06/2011, 09h28
  2. Réponses: 0
    Dernier message: 21/02/2011, 15h58
  3. Réponses: 1
    Dernier message: 11/03/2010, 12h01
  4. Quelques questions à propos de DreamShield
    Par kahoerre dans le forum Dreamshield
    Réponses: 10
    Dernier message: 10/06/2009, 09h44
  5. Quelques question à propos des technologies RAID
    Par DranDane dans le forum Composants
    Réponses: 6
    Dernier message: 12/08/2008, 12h40

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