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 :

Changer un type en un autre en compilation.


Sujet :

Langage C++

  1. #1
    Invité
    Invité(e)
    Par défaut Changer un type en un autre en compilation.
    Salut, je cherche depuis quelque temps déjà un exemple de code simple qui me permettrait de changer un type en un autre en compilation, exactement comme le système des placeholders, mais, avec du type erasure plutôt que avec auto. (qui n'est pas un type et donc, est instockable dans une classe ou bien un contenaire.)

    Je ne sais pas si cela est possible à faire en c++ mais si quelqu'un à un exemple je suis toujours preneur.

  2. #2
    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 suis pas certain de comprendre ce que tu cherches, mais boost.mpl (ou la méta-programmation de manière générale) me semble répondre à la question.

    Un exemple de ce que tu voudrais faire (même si la syntaxe est invalide) permettrait de clarifier ta demande.

  3. #3
    Invité
    Invité(e)
    Par défaut
    Salut, un truc de ce genre :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    Delegate<void> callback1(ptrfunc1, _1, _2, ...);
    Delegate<void> callback2(ptrfunc2, _1, _2, ...);
    std::map<std::string, Delegate<void>> callbacks;
    callbacks.insert(std::make_pair("CB1", callback1);
    callbacks.insert(std::make_pair("CB2", callback2);
    callbacks["CB1"].setParam(1, 2, ...)
    callbacks["CB2"].setParam(1, 2, ...)
    std::map<std::string, Delegate<void>>::iterator it;
    for (it = callbakcs.begin(); it != callback.end(), it++)
         it->second();
    }

  4. #4
    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 vois pas trop où est le caractère "à la compilation" dans ce que tu présentes. Ce sont des placeholders tout ce qu'il y a de plus normaux.

    Tu es en train de vouloir ajouter un système de placeholder à ton delegate ?

  5. #5
    Invité
    Invité(e)
    Par défaut
    Oui en fait c'est ça. Mais je sèche totalement.

    Je voudrais par exemple que si je passe un type au foncteur alors ça me retourner une valeur d'un autre type.

    Faut que j'utilise des classes de traits qui contienne une fonction qui appelle une fonction en fonction du type passé en paramètre template, c'est ça que fait boost::mpl ?

  6. #6
    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
    Le truc c'est qu'un placeholder ça s'utiliserait pas comme ça. Plutôt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Delegate<void> callback1(ptrfunc1, _1, _2, ...);
    callback(1, 2, ...);
    Et que pour des raisons de typage, ça ressemblerait plus à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Delegate<void> callback1(ptrfunc1, _1<T1>(), _2<T2>(), ...);
    callback(1, 2, ...);
    Après pour l'implémentation, faut changer le type stocker dans le tuple pour qu'il erase aussi un placeholder et son utilisation pour lui faire suivre les paramètres d'appel sous forme de void* et qu'il retourne le bon avec le bon type.

  7. #7
    Invité
    Invité(e)
    Par défaut
    Ha, ok, je vois. ^^

    Oui plutôt un truc comme ça.

  8. #8
    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
    Niveau code, par rapport au dernier que j'avais proposé, les changements de base sont :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    template<class T>
    struct ref_val_i
    {
    	//Accès à la donnée
    	virtual T& get() =0;
    	virtual T& get(void*) =0;
    	virtual T& get(void*,void*) =0;
    	//etc avec autant de placeholder que tu veux gérer
    };
    Une nouvelle classe fille template pour ref_val_i qui sert de placeholder et retourne le i-ième void* casté vers le bon type.
    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
     
    template<class R>
    struct delegate_i
    {
    	virtual R operator()() const = 0;
    	virtual R operator()(void*) const = 0;
    	virtual R operator()(void*,void*) const = 0;
    	//etc avec autant de placeholder que tu veux gérer
    };
     
    template<class R, class... ArgT>
    struct delegate_impl : delegate_i<R>
    { 
    	R operator()() const
    	{ return call(std::make_index_sequence<sizeof...(ArgT)>()); }
    	R operator()(void* p1) const
    	{ return call(std::make_index_sequence<sizeof...(ArgT)>(),p1); }
    	R operator()(void* p1, void* p2) const
    	{ return call(std::make_index_sequence<sizeof...(ArgT)>(),p1,p2); }
    	//etc avec autant de placeholder que tu veux gérer
     
    private:
    	template<std::size_t... I, class... Arg>
    	R call(std::index_sequence<I...>,Arg... arg) const
    	{ return func(std::get<I>(param).get(arg...)...); }
    };
     
    template<
    	class R,
    >
    struct delegate {
    	template<class... Arg>
    	R operator()(Arg&&... arg) const
    	{ return (*data)(&arg...); }
    };
    Après faut tester et approfondir la réflexion, mais l'idée de base doit être là. La génération des sections de code qui se répètent doit se faire avec le préprocesseur (boost.pp pour aider).

  9. #9
    Invité
    Invité(e)
    Par défaut
    Mmm, l'idée ne me semble pas si géniale, ne vaudrait t'il pas mieux, passer par des classes de politiques et des listes d'index et faire 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
    14
    15
    16
    17
    18
    19
    20
    21
     
    template <typename T>
    struct _1 {
             static constexpr int i = 1;
    };
    template <typename T>
    struct _2 {
             static constexpr int i = 2;
    };
    etc...
    template <class T, class TP>
    class placeholders_wrapper<Placeholders<T>> {
             public :
             void setTuple(TP tuple)  { this->tuple = tuple; }
             template <typename... T>
             static T get() {
                      return std::get<Placeholders<T>::i>(tuple);
             }
             private :
             TP tuple;
    };

    Plutôt que de passer par void* et des macros.
    Dernière modification par Invité ; 09/10/2014 à 18h16.

  10. #10
    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
    Si tu as la solution, pourquoi tu demandes de l'aide ?

    Ton bout de code est bien jolie, mais je vois pas en quoi il va aider a rendre la syntaxe : my_delegate(a,b) valide. C'est à ça que servent les macro et les void* (on peut utiliser un type dédié plutôt que void* mais ça ne change absolument pas le principe).

  11. #11
    Invité
    Invité(e)
    Par défaut
    Ok, je vais plutôt utilisé un type dédié alors.

  12. #12
    Invité
    Invité(e)
    Par défaut
    Voilà j'ai changé ta classe il me reste le get à faire maintenant mais là j'avoue que je sèche un petit peu, en effet, voici le code :

    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
    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
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    540
    541
    542
    543
    544
    545
    546
    547
    548
    549
    550
    551
    552
    553
    554
    555
    556
    557
    558
    559
    560
    561
    562
    563
    564
    565
    566
    567
    568
    569
    570
    571
    572
    573
    574
    575
    576
    577
    578
    579
    580
    581
    582
    583
    584
    585
    586
    587
    588
    589
    590
    591
    592
    593
    594
    595
    596
    597
    598
    599
    600
    601
    602
    603
    604
    605
    606
    607
    608
    609
    610
    611
    612
    613
    614
    615
    616
    617
    618
    619
    620
    621
    622
    623
    624
    625
    626
    627
    628
    629
    630
    631
    632
    633
    634
    635
    636
    637
    638
    639
    640
    641
    642
    643
    644
    645
    646
    647
     
    #ifndef ODFAEG_FAST_DELEGATE_HPP
    #define ODFAEG_FAST_DELEGATE_HPP
    #include <functional>
    #include <iostream>
    #include "export.hpp"
    #include "erreur.h"
    #include <tuple>
    #include <utility>
    #include <memory>
    /**
      *\namespace odfaeg
      * the namespace of the Opensource Development Framework Adapted for Every Games.
      */
    namespace odfaeg {
    /**
    *  \file  fastDelegate.h
    *  \class IRefVal
    *  \brief Interface for the warppers to references, values and pointers.
    *  This class is used store references, pointers and values to pass to the callack's functions.
    *  \param T : the type of the value to wrap.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template <class T, int I>
    struct Placeholder {
        static constexpr int i = I;
    };
    template <class T>
    using _1 = Placeholder<T, 1>;
    template <class T>
    using _2 = Placeholder<T, 2>;
    template<class T, int I>
    struct IRefVal {
        /**\fn
        *  \brief default constructor
        */
    	IRefVal()=default;
    	/**\fn T& get()
            *  \brief get the reference of the wrapped type.
            *  \return the reference of the wrapped type.
            */
    	virtual Placeholder<T, I>& get() =0;
    	/**\fn std::unique_ptr<IRefVal<T>> clone() const = 0;
            *  \brief copy the wrapper.
            *  \return the copied wrapper.*/
    	virtual std::unique_ptr<IRefVal<T, I>> clone() const = 0;
    	/**\fn destructor*/
    	virtual ~IRefVal(){}
     
    protected:
        /**\fn IRefVal(const IRefVal&)
        *  \brief constructor, pass the reference to wrap.
        *  \param const IRefVal& : the reference to wrap.
        */
    	IRefVal(const IRefVal&){}
    	/** \fn IRefVal& operator=(const IRefVal&)
            *   \brief affector.
            *   \param const IRefVal& : the wrapper to affect.
            *   \return the affected wrapper.*/
    	IRefVal& operator=(const IRefVal&)
    	{ return *this; }
    };
    template<class T>
    struct IRefVal<T, 0> {
        /**\fn
        *  \brief default constructor
        */
    	IRefVal()=default;
    	/**\fn T& get()
            *  \brief get the reference of the wrapped type.
            *  \return the reference of the wrapped type.
            */
    	virtual T& get() =0;
    	/**\fn std::unique_ptr<IRefVal<T>> clone() const = 0;
            *  \brief copy the wrapper.
            *  \return the copied wrapper.*/
    	virtual std::unique_ptr<IRefVal<T, 0>> clone() const = 0;
    	/**\fn destructor*/
    	virtual ~IRefVal(){}
     
    protected:
        /**\fn IRefVal(const IRefVal&)
        *  \brief constructor, pass the reference to wrap.
        *  \param const IRefVal& : the reference to wrap.
        */
    	IRefVal(const IRefVal&){}
    	/** \fn IRefVal& operator=(const IRefVal&)
            *   \brief affector.
            *   \param const IRefVal& : the wrapper to affect.
            *   \return the affected wrapper.*/
    	IRefVal& operator=(const IRefVal&)
    	{ return *this; }
    };
    /**
    *  \file  fastDelegate.h
    *  \class Ref
    *  \brief Warp a reference. (Use std::reference_wrapper so we can pass a reference with std::ref)
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    struct Ref : IRefVal<T, 0> {
        /**
        *\fn Ref(const std::reference_wrapper<T>& r)
        *\brief Constructor : pass an std::reference_wrapper to the wrapper.
        *\param std::reference_wrapper<T>& r : the reference_wrapper.
        */
    	Ref(const std::reference_wrapper<T>& r)
    		: ref(r)
    	{}
    	/**
            * \fn T& get()
            * \brief return a reference to an object.
            * \return T& the reference to the object.
            */
    	T& get()
    	{ return ref.get(); }
    	/**
            * \fn std::unique_ptr<IRefVal<T>> clone() const
            * \brief copy the reference wrapper.
            * \return std::unique_ptr<IRefVal<T>> : the cloned wrapper.
            */
    	std::unique_ptr<IRefVal<T, 0>> clone() const
    	{ return std::make_unique<Ref>(*this); }
    private:
    	std::reference_wrapper<T> ref; /**> the std::reference_wrapper which warp the reference.*/
    };
    /**
    *  \file  fastDelegate.h
    *  \class Val
    *  \brief Warp a value.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    struct Val : IRefVal<T, 0> {
        /**\fn Val(const T& t)
        *  \brief pass a value to the wrapper.
        *  \param const T& t : the value to pass.
        */
    	Val(const T& t)
    		: val(t)
    	{}
    	/** \fn
            *   \brief return the value
            *   \return T& : return the value.
            */
    	T& get()
    	{ return val; }
     
    	/**
            * \fn std::unique_ptr<IRefVal<T>> clone() const
            * \brief copy the value wrapper.
            * \return std::unique_ptr<IRefVal<T>> : the cloned wrapper.
            */
    	std::unique_ptr<IRefVal<T, 0>> clone() const
    	{ return std::make_unique<Val>(*this); }
    private:
    	T val; /**> T val : keep the value of the wrapper.*/
    };
    template <class T, int I>
    struct PlaceholdersWrapper : IRefVal<T, I> {
         PlaceholdersWrapper (Placeholder<T, I> pl) : pl(pl) {
     
         }
         Placeholder<T, I>& get() {
             return pl;
         }
         std::unique_ptr<IRefVal<T, I>> clone() const
    	 { return std::make_unique<PlaceholdersWrapper<T, I>>(*this); }
    private :
         Placeholder<T, I> pl;
    };
    template <class T>
    struct IRefValPl {
        IRefValPl() {}
        virtual std::unique_ptr<IRefValPl<T>> clone() const = 0;
        /**\fn IRefVal(const IRefVal&)
        *  \brief constructor, pass the reference to wrap.
        *  \param const IRefVal& : the reference to wrap.
        */
        protected :
    	IRefValPl(const IRefValPl&){}
    	/** \fn IRefVal& operator=(const IRefVal&)
            *   \brief affector.
            *   \param const IRefVal& : the wrapper to affect.
            *   \return the affected wrapper.*/
    	IRefValPl& operator=(const IRefValPl&)
    	{ return *this; }
    };
    /**
    *  \file  fastDelegate.h
    *  \class Ref
    *  \brief Warp a pointer.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T, int I>
    struct RefVal : IRefValPl<T> {
        RefVal(const Placeholder<T, I>& pl)
    	: rv(std::make_unique<PlaceholdersWrapper<T, I>>(pl))
    	{}
    	RefVal(const RefVal& rhs) {
    	    rv = rhs.rv->clone();
    	}
    	RefVal& operator=(const RefVal& rhs)
    	{ rv=rhs.rv->clone(); return *this; }
    	/** \fn T& get() const
            *   \brief get the wrapper.
            *   \return a unique pointer to the generic wrapper interface.
            */
    	std::unique_ptr<IRefValPl<T>> clone() const {
    	    return std::make_unique<RefVal<T, I>>(*this);
    	}
    	Placeholder<T, I>& get() const
    	{ return rv->get(); }
     
    private:
    	std::unique_ptr<IRefVal<T, I>> rv; /**> a pointer to the generic wrapper interface.*/
    };
    template<class T>
    struct RefVal<T, 0> : IRefValPl<T> {
        /**
        * \fn RefVal (const T& t)
        * \brief constructor : construct a wrapper to a value
        * \param const T& t : the value to
        */
    	RefVal(const T& t)
    	: rv(std::make_unique<Val<T>>(t))
    	{}
    	/**
        * \fn RefVal (const std::reference_wrapper<T>& r)
        * \brief constructor : construct a wrapper to an std::reference_wrapper.
        * \param const std::reference_wrapper<T>& : the std::reference_wrapper to pass.
        */
    	RefVal(const std::reference_wrapper<T>& r)
    	: rv(std::make_unique<Ref<T>>(r))
    	{}
    	RefVal(const RefVal& rhs) {
    	    rv = rhs.rv->clone();
    	}
    	RefVal(const RefVal&& rhs) {
            rv = rhs.rv->clone();
    	}
    	RefVal& operator=(const RefVal& rhs)
    	{ rv=rhs.rv->clone(); return *this; }
    	RefVal& operator=(const RefVal&& rhs)
    	{ rv=rhs.rv->clone(); return *this; }
    	/** \fn T& get() const
            *   \brief get the wrapper.
            *   \return a unique pointer to the generic wrapper interface.
            */
    	std::unique_ptr<IRefValPl<T>> clone() const {
    	    return std::make_unique<RefVal<T, 0>>(*this);
    	}
     
    private:
    	std::unique_ptr<IRefVal<T, 0>> rv; /**> a pointer to the generic wrapper interface.*/
    };
    template <class T>
    struct RefValPl {
        /**
        * \fn RefVal (const T& t)
        * \brief constructor : construct a wrapper to a value
        * \param const T& t : the value to
        */
    	RefValPl(const T& t) :
        rvpl(std::make_unique<RefVal<T, 0>>(t))
    	{}
    	/**
        * \fn RefVal (const std::reference_wrapper<T>& r)
        * \brief constructor : construct a wrapper to an std::reference_wrapper.
        * \param const std::reference_wrapper<T>& : the std::reference_wrapper to pass.
        */
    	RefValPl(const std::reference_wrapper<T>& r) :
        rvpl(std::make_unique<RefVal<T, 0>>(r))
    	{}
    	template <int I>
    	RefValPl(Placeholder<T, I>&& pl) :
        rvpl(std::make_unique<RefVal<T, I>>(pl))
    	{}
    	RefValPl(const RefValPl& rhs) {
    	    rvpl = rhs.rvpl->clone();
    	}
    	RefValPl(RefValPl&& rhs) {
    	    rvpl = rhs.rvpl->clone();
    	}
    	/** \fn RefVal& operator= (const RefVal& rhs)
            *   \brief affector.
            *   \param const RefVal& rhs : the wrapper to affect.
            */
    	RefValPl& operator=(const RefValPl& rhs)
    	{ rvpl=rhs.rvpl->clone(); return *this; }
    	RefValPl& operator=(RefValPl&& rhs)
    	{ rvpl=rhs.rvpl->clone(); return *this; }
    	/** \fn T& get() const
            *   \brief get the wrapper.
            *   \return a unique pointer to the generic wrapper interface.
            */
        private:
        std::unique_ptr<IRefValPl<T>> rvpl; /**> a pointer to the generic wrapper interface.*/
    };
    //Classe de trait pour déterminer le type à stocker
     
    //(Interne) Cas général
    /**
    *  \file  fastDelegate.h
    *  \class ToStoreImpl
    *  \param T the type of the wrapper.
    *  \brief Trait class which use an alias on a wrapped type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    struct ToStoreImpl
    { using type = T; };
    /**
    *  \file  fastDelegate.h
    *  \class ToStoreImpl
    *  \param T the type warpped in the warpper.
    *  \brief Trait class with keep an alias on the wrapped type.
    *  This class is specialized for std::_reference_wrapper type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    struct ToStoreImpl<std::reference_wrapper<T>>
    { using type = T; };
    template<class T, int I>
    struct ToStoreImpl<Placeholder<T, I>>
    { using type = T; };
     
    /**
    *  \file  fastDelegate.h
    *  \class ToStore
    *  \param T the type of the wrapper.
    *  \brief Trait class with keep an alias of the wrapper type. (without the reference)
    *  the inheritance use the right specialized templated class to hold the type of the wrapped object
    *  depending on the wrapper type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    struct ToStore
    	: ToStoreImpl<std::remove_reference_t<T>>
    {};
    /**
    *  \file  fastDelegate.h
    *  \class ToStore_t
    *  \param T the type of the wrapped object.
    *  \brief Trait class which hold an alias to the real type of the wrapped type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    using ToStore_t = typename
    	ToStore<T>::type;
    /**
    *  \file  fastDelegate.h
    *  \class DynamicWrapper
    *  \param R the return type of the wrapped functor.
    *  \param C the class type of the wrapped functor.
    *  \param ArgT the arguments types of the wrapped functor.
    *  \brief This class warp a function pointer to a member function.
    *  I don't use an std::function directly here to keep the class type of the member function pointer
    *  because if the passed object is polymorphic, I need to apply a dynamic cast
    *  before calling the member function pointer on the object.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class R, class C, class... ArgT>
    struct DynamicWrapper {
        /**\fn DynamicWrapper(R(C::*pf)(ArgT...)) : pfunc(pf)
        *  \brief warp a pointer to a member function.
        *  \param R(C::*pf)(ArgT...) : the pointer to the member function.
        */
    	DynamicWrapper(R(C::*pf)(ArgT...)) : pfunc(pf){}
    	/**\fn R operator()(O* o, ArgU&&... arg) const
            *  \brief call the member function's pointer witht he given object and the given argument
            *  apply a dynamic_cast in case of the type of the object and the type of the classe containing the member function
            *  are not the same. (If the object is polymoprhic)
            *  If the cast fails it means that the object is not polymorphic so it throws an error.
            *  \param O* o : the object onwich to call the member function's pointer.
            *  \param ArgU&& arg : the arguments of the member function's pointer to call.
            */
    	template<class O, class... ArgU>
    	R operator()(O* o, ArgU&&... arg) const
    	{
    	    if(dynamic_cast<C*>(o))
    			return (dynamic_cast<C*>(o)->*pfunc)(std::forward<ArgU>(arg)...);
            throw Erreur(0, "Invalid cast : types are nor polymorphic!", 1);
    	}
    	template<class O, class... ArgU>
    	R operator()(O& o, ArgU&&... arg) const
    	{
    		if(dynamic_cast<C&>(o))
    			return (dynamic_cast<C&>(o).*pfunc)(std::forward<ArgU>(arg)...);
            throw Erreur(0, "Invalid cast : types are nor polymorphic!", 1);
    	}
    private:
    	R (C::*pfunc)(ArgT...); /**> a pointer to a member's function.*/
    };
    /**
    *  \file  fastDelegate.h
    *  \class DynamicFunction
    *  \param F the type of the function.
    *  \brief Generic class for every functors type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class F>
    class DynamicFunction;
    /**
    *  \file  fastDelegate.h
    *  \class DynamicFunction
    *  \param R the return type of the function.
    *  \param ArgT... the type of the arguments of the function.
    *  \brief Specialized template class for functors. (inherit from std::function)
    *  build a functor with the right constructor depending a the pointer's function type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class R, class... ArgT>
    class DynamicFunction<R(ArgT...)>
    	: std::function<R(ArgT...)>
    {
        /**> just an alias to the type of the base class.*/
    	using Base = std::function<R(ArgT...)>;
     
    public:
        /**
        * \fn DynamicFunction(F&& f)
        * \brief pass a functor to the std::function.
        * \param F&& f : the functor to pass to the std::function.
        */
    	template<class F>
    	DynamicFunction(F&& f) : Base(std::forward<F>(f))
    	{}
    	/** \fn DynamicFunction (R (C::*pf)(ArgU...))
            *   \brief pass a pointer to a member's function to the DynamicWrapper, and then
            *   pass this wrapper to the std::function, so, the std::function call the operator() of the DynamicWrapper class
            *   and not the operator() of the std::function class so we can perform the dynamic_cast if necessary.
            *   \param R(C::*pf)(ArgU...) : the pointer to the member's function.
            *   \
            */
    	template<class C, class... ArgU>
    	DynamicFunction(R(C::*pf)(ArgU...))
    		: Base(DynamicWrapper<R,C,ArgU...>(pf))
    	{}
    	/**> just an allias to the operator() of the base class.*/
        using Base::operator();
    };
    /**
    *  \file  fastDelegate.h
    *  \class Delegate
    *  \param R the return type of the function.
    *  \brief Interface with can hold a delegate to every delegates types.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class R>
    struct Delegate {
        /**\fn Delegate()
        *  \brief default constructor.
        */
    	Delegate() =default;
    	/**\fn virtual std::unique_ptr<Delegate> clone() const = 0;
        *  \brief pure virtual function to redefine in the subclass to copy the delegate.
        *  \return std::unique_ptr<Delegate> a pointer to the copied delegate.
        */
    	virtual std::unique_ptr<Delegate> clone() const = 0;
    	/**\fn R operator()() = 0;
        *  \brief pure virtual function to redefines to call the std::function of the delegate.
        *  \return R : return the value returned by the std::function.
        */
    	virtual R operator()() = 0;
    	/** /fn virtual Delegate()
            * \brief destructor
            */
    	virtual ~Delegate(){}
     
    protected:
        /**
        * \fn Delegate (const Delegate&) {}
        * \brief copy constructor.
        * \param const Delegate& : the delegate to copy.
        */
    	Delegate(const Delegate&){}
    	/**
        * \fn Delegate& operator= (const Delegate&) {}
        * \brief affector.
        * \return Delegate& : return a reference to the current delegate.
        */
    	Delegate& operator=(const Delegate&)
    	{
            return *this;
    	}
    };
    /**
    *  \file  fastDelegate.h
    *  \class FastDelegateImpl
    *  \brief Implementation of the delegate's interfaces.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class R, class... ArgT>
    struct FastDelegateImpl : Delegate<R> {
        /** \fn FastDelegateImpl(F&& f, ArgU&&... arg)
        *   \brief constructor : create the delegate with the functor and the arguments value passed.
        */
    	template<class F, class... ArgU>
    	FastDelegateImpl(F&& f, ArgU&&... arg)
    		: func(std::forward<F>(f))
    		, param(std::forward<ArgU>(arg)...)
    	{}
    	/** \fn std::unique_ptr<Delegate<R>> clone() const
        *   \brief make a copy of the delegate.
        *   \return the copied delegate.
        */
    	std::unique_ptr<Delegate<R>> clone() const
    	{ return std::make_unique<FastDelegateImpl>(*this); }
    	/** \fn R operator()()
            *   \brief call the std::function of the delegate.
        *   \return the value returned by the std::function.
        */
    	R operator()()
    	{ return call(std::make_index_sequence<sizeof...(ArgT)>()); }
    	/** \fn R operator()()
            *   \brief changed the parameter's values of the std::function.
        *   \param ArgU&&... args : the values for the parameters to the delegate's function.
        */
    	template<class... ArgU>
    	void setParams(ArgU&&... arg)
    	{ param=std::make_tuple(std::forward<ArgU>(arg)...); }
     
    private:
        /** \fn R call(std::index_sequence<I...>)
            *   \brief pass each elements of the tuple to the std::function and unwarp them.
        *   \param std::index_sequence<I...> : a sequence of indexes to get every elements of the tuple.
        *   \return the value returned by the std::function.
        */
    	template<std::size_t... I>
    	R call(std::index_sequence<I...>)
    	{ return func(std::get<I>(param).get()...); }
    	DynamicFunction<R(ArgT&...)> func; /**> a functor whith hold the pointer to a callback function.*/
    	std::tuple<RefValPl<ArgT>...> param; /**> the wrapped values of the parameters to pass to the callback's function.*/
    };
    /**
    *  \file  fastDelegate.h
    *  \class FastDelegate
    *  \brief Class used for the type erasure,
    *  which allow the user be able to store a set of different callback's functions types with the same return type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class R>
    struct FastDelegate {
        /**\fn default constructor
        */
        FastDelegate() = default;
        /**\fn FastDelegate (F&& f, Arg&& arf)
        *  \param F&& f : the functor to pass.
        *  \param Arg&&... arg : arguments to pass to the functor.
        */
        template<class F, class... Arg>
    	FastDelegate(F&& f, Arg&&... arg) :
    		delegate(std::make_unique
    			<FastDelegateImpl<R,ToStore_t<Arg>...>>
    			(std::forward<F>(f),std::forward<Arg>(arg)...)
    		)
    	{}
     
    	/**\fn FastDelegate (FastDelegate& rhs)
            *  \brief copy constructor.
            *  \param FastDelegate& rhs : the delegate to copy.
            */
    	FastDelegate(FastDelegate& rhs)
    		: delegate(rhs.delegate->clone())
    	{}
    	/**\fn FastDelegate (const FastDelegate& rhs)
            *  \brief copy constructor.
            *  \param const FastDelegate& rhs : the delegate to copy.
            */
    	FastDelegate(const FastDelegate& rhs)
    		: delegate(rhs.delegate->clone())
    	{}
    	/**\fn FastDelegate (FastDelegate& rhs)
            *  \brief move constructor.
            *  \param FastDelegate&& rhs : the delegate to move.
            */
    	FastDelegate(FastDelegate&& rhs) =default;
    	/**\fn FastDelegate& operator= (FastDelegate& rhs)
            *  \brief affect the content of the delegate to the delegate.
            *  \param const FastDelegate& rhs : the delegate affect.
            *  \return FastDelegate& : the affected delegate.
            */
    	FastDelegate& operator=(const FastDelegate& rhs)
    	{ return operator=(FastDelegate(rhs)); }
    	/**\fn FastDelegate& operator= (FastDelegate& rhs)
            *  \brief affect and move the content of the delegate to the delegate.
            *  \param const FastDelegate& rhs : the delegate to move and to affect.
            *  \return FastDelegate& : the moved and affected delegate.
            */
    	FastDelegate& operator=(FastDelegate&&) =default;
    	/**\fn R operator()() const;
            *  \brief call the std::function of the delegate.
            *  \return the value returned by the std::function.
            */
    	R operator()() const
    	{ return (*delegate)(); }
    	/**\fn setParams(Arg&&... arg)
            *  \brief change the parameter's values of the delegate.
            *  \return Arg&&... arg : the values of the parameters of the delegate.
            */
    	template<class... Arg>
    	void setParams(Arg&&... arg)
    	{
    		using DynamicType =
    			FastDelegateImpl<R,ToStore_t<Arg>...>*;
    		if (dynamic_cast<DynamicType>(delegate.get()))
               dynamic_cast<DynamicType>(delegate.get())->setParams(std::forward<Arg>(arg)...);
            else
                throw Erreur(0, "Bad cast : you've passed a pointer to an object of a derived type as functor argument to the constructor,\n"
                             "which is not compatible with an argument of a base type passed to setParams!\n"
                             "Make a static cast from the derived object to the base object type when passing the argument to the constructor.\n"
                             "Exemple : FastDelegate<void> fd(ptrfunc, static_cast<Base*>(new Derived()); Base* b = &derived; fd.setParams(b)", 1);
    	}
    private:
    	std::unique_ptr<Delegate<R>> delegate; /**> holds the pointer to the generic delegate.*/
    };
    }
    #endif

    Je me retrouve avec un tuple contenant des valeurs et des placeholders et ce que je voudrais faire maintenant c'est, si l'élément du tuple est un placeholder alors j'appelle une fonction, sinon, j'appelle une autre fonction, est ce que c'est possible un truc du genre à ça ?

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    template <typename... Arg1, typename...Arg2>
    void get(std::tuple<Args1> param1, std::tuple<Arg2> param2) {
           get(std::make_index_sequence<sizeof...(Arg1)>(), param1, param2);
    }
    template<std::size_t... I,typename... Arg1,typename Arg2>
    R call(std::index_sequence<I...>, std::tuple<Arg2> param1, std::tuple<Arg2> param2)
    { return func(std::get<I>(param1).get()...); }
    template<std::size_t... I,typename... Arg1,typename Arg2>
    R call(std::index_sequence<I...>, std::tuple<Arg2> param1,  std::tuple<Arg2> param2)
    { return func(std::get<std::get<param1.get()::i>>(param2).get()...); }

  13. #13
    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 vois pas les éléments que j'ai indiqué dans mon avant dernier message dans ton code.

    Quand on veut implémenter une fonctionnalité, la première chose à faire c'est de définir l'interface. En l’occurrence permettre à l'opérateur d'appel de supporter plusieurs paramètres. Le système que tu implémentes étant un transfère d'appel d'opérateur d'appel, il faut que chacun de ces opérateurs puissent supporter plusieurs paramètres, certain de ces opérateurs étant virtuel on se retrouve avec la nécessité de prendre les paramètres en void* (ou une capsule, mais dans le contexte je ne vois pas l'intérêt de faire une capsule dédiée). Le raisonnement se prolonge directement sur get.

    Je ne vois rien de tout ça dans ton code pour le moment.

    C'est quoi ces param1 / param2 ? Je pense deviner que param1 c'est le param actuel, mais le param2 c'est quoi ? Si c'est sensé être un tuple contenant les éléments à mettre à la place des placeholders, tu peux abandonner cette idée (tu aurais commencé par modifier ton interface tu aurais vu tout de suite que ça ne peut pas convenir, tu ne peux pas conserver le type des éléments à mettre à la place dans un système où tu supprimes totalement l'information sur le type des paramètres).

  14. #14
    Invité
    Invité(e)
    Par défaut
    Ok oui je vois, si je supprime l'information sur un paramètre et que je la met dans le tuple, je ne peux récupérer i après ce qui est gênant.

    Sinon je pensais faire un système avec 2 listes (deux tuples), et si le type est un placeholder, bah, je le remplace par l'élement n°i du second tuple.

    Bref, faut que je transmettent les params à RefVal directement, qui lui, possèdes l'information sur les paramètres..., à partir de là, je pourrait sûrement faire une interface

  15. #15
    Invité
    Invité(e)
    Par défaut
    Sinon, une question, n'y a t'il pas moyen de faire du SFINAE avec des templates variadiques, 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
    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
     
    template<class R, class... ArgT>
    struct FastDelegateImpl : Delegate<R> {
        /** \fn FastDelegateImpl(F&& f, ArgU&&... arg)
        *   \brief constructor : create the delegate with the functor and the arguments value passed.
        */
    	template<class F>
    	FastDelegateImpl(F&& f, RefVal<ArgT, 0>&&... arg)
    		: func(std::forward<F>(f))
    		, param(std::forward<RefVal<ArgT, 0>>(arg)...)
    	{}
    	/** \fn std::unique_ptr<Delegate<R>> clone() const
        *   \brief make a copy of the delegate.
        *   \return the copied delegate.
        */
    	std::unique_ptr<Delegate<R>> clone() const
    	{ return std::make_unique<FastDelegateImpl>(*this); }
    	/** \fn R operator()()
            *   \brief call the std::function of the delegate.
        *   \return the value returned by the std::function.
        */
    	R operator()()
    	{ return call(std::make_index_sequence<sizeof...(ArgT)>()); }
    	/** \fn R operator()()
            *   \brief changed the parameter's values of the std::function.
        *   \param ArgU&&... args : the values for the parameters to the delegate's function.
        */
    	template<class... ArgU>
    	void setParams(ArgU&&... arg)
    	{ param=std::make_tuple(std::forward<ArgU>(arg)...); }
     
    private:
        /** \fn R call(std::index_sequence<I...>)
            *   \brief pass each elements of the tuple to the std::function and unwarp them.
        *   \param std::index_sequence<I...> : a sequence of indexes to get every elements of the tuple.
        *   \return the value returned by the std::function.
        */
    	template<std::size_t... I>
    	R call(std::index_sequence<I...>)
    	{ return func(std::get<I>(param).get()...); }
    	DynamicFunction<R(ArgT&...)> func; /**> a functor whith hold the pointer to a callback function.*/
    	std::tuple<RefVal<ArgT, 0>...> param; /**> the wrapped values of the parameters to pass to the callback's function.*/
    };
    template<class R, class... ArgT, int... PLI>
    struct FastDelegateImpl<R, Placeholder<ArgT, PLI>...> : Delegate<R> {
        /** \fn FastDelegateImpl(F&& f, ArgU&&... arg)
        *   \brief constructor : create the delegate with the functor and the arguments value passed.
        */
    	template<class F, int... N, class = typename std::enable_if<N <= 2>::type>
    	FastDelegateImpl(F&& f, RefVal<ArgT, N>&&... arg)
    		: func(std::forward<F>(f))
    		, placeholders(std::forward<RefVal<ArgT, N>>(arg)...)
    	{}
    	/** \fn std::unique_ptr<Delegate<R>> clone() const
        *   \brief make a copy of the delegate.
        *   \return the copied delegate.
        */
    	std::unique_ptr<Delegate<R>> clone() const
    	{ return std::make_unique<FastDelegateImpl>(*this); }
    	/** \fn R operator()()
            *   \brief call the std::function of the delegate.
        *   \return the value returned by the std::function.
        */
    	R operator()()
    	{ return call(std::make_index_sequence<sizeof...(ArgT)>()); }
    	/** \fn R operator()()
            *   \brief changed the parameter's values of the std::function.
        *   \param ArgU&&... args : the values for the parameters to the delegate's function.
        */
    	template<class... ArgU>
    	void setParams(ArgU&&... arg)
    	{ placeholders=std::make_tuple(std::forward<ArgU>(arg)...); }
     
    private:
        /** \fn R call(std::index_sequence<I...>)
            *   \brief pass each elements of the tuple to the std::function and unwarp them.
        *   \param std::index_sequence<I...> : a sequence of indexes to get every elements of the tuple.
        *   \return the value returned by the std::function.
        */
    	template<std::size_t... I>
    	R call(std::index_sequence<I...>)
    	{ return func(std::get<I>(placeholders).get()...); }
    	DynamicFunction<R(ArgT&...)> func; /**> a functor whith hold the pointer to a callback function.*/
    	std::tuple<RefVal<ArgT, PLI>...> placeholders; /**> the wrapped values of the parameters to pass to the callback's function.*/
    };

    Ainsi, si l'argument passé est un placeholder, je le mets dans un tuple, sinon, je le met dans un autre tuple, et à la fin, je passe le tuple final. (la concaténation des deux autres tuples)
    Dernière modification par Invité ; 10/10/2014 à 16h53.

  16. #16
    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
    Non, le type de ton tuple doit être fixé et valide en cas de changement de paramètre, c'est pas le cas avec ce que tu proposes. Honnêtement je ne suis pas convaincu qu'il existe une autre solution fondamentalement différente de celle que je t'ai proposé.

  17. #17
    Invité
    Invité(e)
    Par défaut
    Haaa voilaaaa!!!!

    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
    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
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    540
    541
    542
    543
    544
    545
    546
    547
    548
    549
    550
    551
    552
    553
    554
    555
    556
    557
    558
    559
    560
    561
    562
    563
    564
    565
    566
    567
    568
    569
    570
    571
    572
    573
    574
    575
    576
    577
    578
    579
    580
    581
    582
    583
    584
    585
    586
    587
    588
    589
    590
    591
    592
    593
    594
    595
    596
    597
    598
    599
    600
    601
    602
    603
    604
    605
    606
    607
    608
    609
    610
    611
    612
    613
    614
    615
    616
    617
    618
    619
    620
    621
    622
    623
    624
    625
    626
    627
    628
    629
    630
    631
    632
    633
    634
    635
    636
    637
    638
    639
    640
    641
    642
    643
    644
    645
    646
    647
    648
    649
    650
    651
    652
    653
    654
    655
    656
    657
    658
    659
    660
    661
    662
    663
    664
    665
     
    //#include "application.h"
    #include <fstream>
    #include "odfaeg/Core/fastDelegate.h"
    #include <functional>
    #include <iostream>
    #include <tuple>
    #include <utility>
    #include <memory>
    #include "../include/odfaeg/Core/erreur.h"
    /**
    *  \file  fastDelegate.h
    *  \class IRefVal
    *  \brief Interface for the warppers to references, values and pointers.
    *  This class is used store references, pointers and values to pass to the callack's functions.
    *  \param T : the type of the value to wrap.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template <class T, int I>
    struct Placeholder {
        static constexpr int i = I;
        using type = T;
    };
    template <class T>
    using _1 = Placeholder<T, 1>;
    template <class T>
    using _2 = Placeholder<T, 2>;
    template <typename T>
    struct is_placeholder {
        static constexpr bool value = false;
    };
    template <typename T, int I>
    struct is_placeholder<Placeholder<T, I>> {
        static constexpr bool value = true;
    };
    template <typename T, int I>
    struct IRefVal {
        /**\fn
        *  \brief default constructor
        */
    	IRefVal()=default;
    	/**\fn T& get()
            *  \brief get the reference of the wrapped type.
            *  \return the reference of the wrapped type.
            */
    	virtual Placeholder<T, I>& get() =0;
    	/**\fn std::unique_ptr<IRefVal<T>> clone() const = 0;
            *  \brief copy the wrapper.
            *  \return the copied wrapper.*/
    	virtual std::unique_ptr<IRefVal<T, I>> clone() const = 0;
    	/**\fn destructor*/
    	virtual ~IRefVal(){}
     
    protected:
        /**\fn IRefVal(const IRefVal&)
        *  \brief constructor, pass the reference to wrap.
        *  \param const IRefVal& : the reference to wrap.
        */
    	IRefVal(const IRefVal&){}
    	/** \fn IRefVal& operator=(const IRefVal&)
            *   \brief affector.
            *   \param const IRefVal& : the wrapper to affect.
            *   \return the affected wrapper.*/
    	IRefVal& operator=(const IRefVal&)
    	{ return *this; }
    };
    template<class T>
    struct IRefVal<T, 0> {
        /**\fn
        *  \brief default constructor
        */
    	IRefVal()=default;
    	/**\fn T& get()
            *  \brief get the reference of the wrapped type.
            *  \return the reference of the wrapped type.
            */
    	virtual T& get() =0;
    	/**\fn std::unique_ptr<IRefVal<T>> clone() const = 0;
            *  \brief copy the wrapper.
            *  \return the copied wrapper.*/
    	virtual std::unique_ptr<IRefVal<T, 0>> clone() const = 0;
    	/**\fn destructor*/
    	virtual ~IRefVal(){}
     
    protected:
        /**\fn IRefVal(const IRefVal&)
        *  \brief constructor, pass the reference to wrap.
        *  \param const IRefVal& : the reference to wrap.
        */
    	IRefVal(const IRefVal&){}
    	/** \fn IRefVal& operator=(const IRefVal&)
            *   \brief affector.
            *   \param const IRefVal& : the wrapper to affect.
            *   \return the affected wrapper.*/
    	IRefVal& operator=(const IRefVal&)
    	{ return *this; }
    };
    /**
    *  \file  fastDelegate.h
    *  \class Ref
    *  \brief Warp a reference. (Use std::reference_wrapper so we can pass a reference with std::ref)
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    struct Ref : IRefVal<T, 0> {
        /**
        *\fn Ref(const std::reference_wrapper<T>& r)
        *\brief Constructor : pass an std::reference_wrapper to the wrapper.
        *\param std::reference_wrapper<T>& r : the reference_wrapper.
        */
    	Ref(const std::reference_wrapper<T>& r)
    		: ref(r)
    	{}
    	/**
            * \fn T& get()
            * \brief return a reference to an object.
            * \return T& the reference to the object.
            */
    	T& get()
    	{ return ref.get(); }
    	/**
            * \fn std::unique_ptr<IRefVal<T>> clone() const
            * \brief copy the reference wrapper.
            * \return std::unique_ptr<IRefVal<T>> : the cloned wrapper.
            */
    	std::unique_ptr<IRefVal<T, 0>> clone() const
    	{ return std::make_unique<Ref>(*this); }
    private:
    	std::reference_wrapper<T> ref; /**> the std::reference_wrapper which warp the reference.*/
    };
    /**
    *  \file  fastDelegate.h
    *  \class Val
    *  \brief Warp a value.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    struct Val : IRefVal<T, 0> {
        /**\fn Val(const T& t)
        *  \brief pass a value to the wrapper.
        *  \param const T& t : the value to pass.
        */
    	Val(const T& t)
    		: val(t)
    	{}
    	/** \fn
            *   \brief return the value
            *   \return T& : return the value.
            */
    	T& get()
    	{ return val; }
     
    	/**
            * \fn std::unique_ptr<IRefVal<T>> clone() const
            * \brief copy the value wrapper.
            * \return std::unique_ptr<IRefVal<T>> : the cloned wrapper.
            */
    	std::unique_ptr<IRefVal<T, 0>> clone() const
    	{ return std::make_unique<Val>(*this); }
    private:
    	T val; /**> T val : keep the value of the wrapper.*/
    };
    template <class T, int I>
    struct PlaceholdersWrapper : IRefVal<T, I> {
         PlaceholdersWrapper (Placeholder<T, I> pl) : pl(pl) {
     
         }
         Placeholder<T, I>& get() {
             return pl;
         }
         std::unique_ptr<IRefVal<T, I>> clone() const
    	 { return std::make_unique<PlaceholdersWrapper<T, I>>(*this); }
    private :
         Placeholder<T, I> pl;
    };
    /**
    *  \file  fastDelegate.h
    *  \class Ref
    *  \brief Warp a pointer.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T, int I>
    struct RefVal {
        RefVal(const Placeholder<T, I>& pl)
    	: rv(std::make_unique<PlaceholdersWrapper<T, I>>(pl))
    	{}
    	RefVal(const RefVal& rhs) {
    	    rv = rhs.rv->clone();
    	}
    	RefVal& operator=(const RefVal& rhs)
    	{ rv=rhs.rv->clone(); return *this; }
    	/** \fn T& get() const
            *   \brief get the wrapper.
            *   \return a unique pointer to the generic wrapper interface.
            */
    	Placeholder<T, I>& get() const
    	{ return rv->get(); }
    private:
    	std::unique_ptr<IRefVal<T, I>> rv; /**> a pointer to the generic wrapper interface.*/
    };
    template<class T>
    struct RefVal<T, 0> {
        /**
        * \fn RefVal (const T& t)
        * \brief constructor : construct a wrapper to a value
        * \param const T& t : the value to
        */
    	RefVal(const T& t)
    	: rv(std::make_unique<Val<T>>(t))
    	{}
    	/**
        * \fn RefVal (const std::reference_wrapper<T>& r)
        * \brief constructor : construct a wrapper to an std::reference_wrapper.
        * \param const std::reference_wrapper<T>& : the std::reference_wrapper to pass.
        */
    	RefVal(const std::reference_wrapper<T>& r)
    	: rv(std::make_unique<Ref<T>>(r))
    	{}
    	RefVal(const RefVal& rhs) {
    	    rv = rhs.rv->clone();
    	}
    	RefVal(const RefVal&& rhs) {
            rv = rhs.rv->clone();
    	}
    	RefVal& operator=(const RefVal& rhs)
    	{ rv=rhs.rv->clone(); return *this; }
    	RefVal& operator=(const RefVal&& rhs)
    	{ rv=rhs.rv->clone(); return *this; }
    	/** \fn T& get() const
            *   \brief get the wrapper.
            *   \return a unique pointer to the generic wrapper interface.
            */
    private:
    	std::unique_ptr<IRefVal<T, 0>> rv; /**> a pointer to the generic wrapper interface.*/
    };
    //Classe de trait pour déterminer le type à stocker
     
    //(Interne) Cas général
    /**
    *  \file  fastDelegate.h
    *  \class ToStoreImpl
    *  \param T the type of the wrapper.
    *  \brief Trait class which use an alias on a wrapped type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    struct ToStoreImpl1
    { using type = T; };
    /**
    *  \file  fastDelegate.h
    *  \class ToStoreImpl
    *  \param T the type warpped in the warpper.
    *  \brief Trait class with keep an alias on the wrapped type.
    *  This class is specialized for std::_reference_wrapper type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    struct ToStoreImpl1<std::reference_wrapper<T>>
    { using type = T; };
    template<class T, int I>
    struct ToStoreImpl1<Placeholder<T, I>>
    { using type = Placeholder<T, I>; };
     
    /**
    *  \file  fastDelegate.h
    *  \class ToStore
    *  \param T the type of the wrapper.
    *  \brief Trait class with keep an alias of the wrapper type. (without the reference)
    *  the inheritance use the right specialized templated class to hold the type of the wrapped object
    *  depending on the wrapper type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    struct ToStore1
    	: ToStoreImpl1<std::remove_reference_t<T>>
    {};
    /**
    *  \file  fastDelegate.h
    *  \class ToStore_t
    *  \param T the type of the wrapped object.
    *  \brief Trait class which hold an alias to the real type of the wrapped type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    using ToStore_t = typename
    	ToStore1<T>::type;
    //Classe de trait pour déterminer le type à stocker
     
    //(Interne) Cas général
    /**
    *  \file  fastDelegate.h
    *  \class ToStoreImpl
    *  \param T the type of the wrapper.
    *  \brief Trait class which use an alias on a wrapped type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    struct ToStoreImpl2
    { using type = T; };
    /**
    *  \file  fastDelegate.h
    *  \class ToStoreImpl
    *  \param T the type warpped in the warpper.
    *  \brief Trait class with keep an alias on the wrapped type.
    *  This class is specialized for std::_reference_wrapper type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    struct ToStoreImpl2<std::reference_wrapper<T>>
    { using type = T; };
    template<class T, int I>
    struct ToStoreImpl2<Placeholder<T, I>>
    { using type = T; };
     
    /**
    *  \file  fastDelegate.h
    *  \class ToStore
    *  \param T the type of the wrapper.
    *  \brief Trait class with keep an alias of the wrapper type. (without the reference)
    *  the inheritance use the right specialized templated class to hold the type of the wrapped object
    *  depending on the wrapper type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    struct ToStore2
    	: ToStoreImpl2<std::remove_reference_t<T>>
    {};
    /**
    *  \file  fastDelegate.h
    *  \class ToStore_t
    *  \param T the type of the wrapped object.
    *  \brief Trait class which hold an alias to the real type of the wrapped type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    using ToStore_f = typename
    	ToStore2<T>::type;
    /**
    *  \file  fastDelegate.h
    *  \class DynamicWrapper
    *  \param R the return type of the wrapped functor.
    *  \param C the class type of the wrapped functor.
    *  \param ArgT the arguments types of the wrapped functor.
    *  \brief This class warp a function pointer to a member function.
    *  I don't use an std::function directly here to keep the class type of the member function pointer
    *  because if the passed object is polymorphic, I need to apply a dynamic cast
    *  before calling the member function pointer on the object.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class R, class C, class... ArgT>
    struct DynamicWrapper {
        /**\fn DynamicWrapper(R(C::*pf)(ArgT...)) : pfunc(pf)
        *  \brief warp a pointer to a member function.
        *  \param R(C::*pf)(ArgT...) : the pointer to the member function.
        */
    	DynamicWrapper(R(C::*pf)(ArgT...)) : pfunc(pf){}
    	/**\fn R operator()(O* o, ArgU&&... arg) const
            *  \brief call the member function's pointer witht he given object and the given argument
            *  apply a dynamic_cast in case of the type of the object and the type of the classe containing the member function
            *  are not the same. (If the object is polymoprhic)
            *  If the cast fails it means that the object is not polymorphic so it throws an error.
            *  \param O* o : the object onwich to call the member function's pointer.
            *  \param ArgU&& arg : the arguments of the member function's pointer to call.
            */
    	template<class O, class... ArgU>
    	R operator()(O* o, ArgU&&... arg) const
    	{
    	    if(dynamic_cast<C*>(o))
    			return (dynamic_cast<C*>(o)->*pfunc)(std::forward<ArgU>(arg)...);
            throw odfaeg::Erreur(0, "Invalid cast : types are nor polymorphic!", 1);
    	}
    	template<class O, class... ArgU>
    	R operator()(O& o, ArgU&&... arg) const
    	{
    		if(dynamic_cast<C&>(o))
    			return (dynamic_cast<C&>(o).*pfunc)(std::forward<ArgU>(arg)...);
            throw odfaeg::Erreur(0, "Invalid cast : types are nor polymorphic!", 1);
    	}
    private:
    	R (C::*pfunc)(ArgT...); /**> a pointer to a member's function.*/
    };
    /**
    *  \file  fastDelegate.h
    *  \class DynamicFunction
    *  \param F the type of the function.
    *  \brief Generic class for every functors type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class F>
    class DynamicFunction;
    /**
    *  \file  fastDelegate.h
    *  \class DynamicFunction
    *  \param R the return type of the function.
    *  \param ArgT... the type of the arguments of the function.
    *  \brief Specialized template class for functors. (inherit from std::function)
    *  build a functor with the right constructor depending a the pointer's function type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class R, class... ArgT>
    class DynamicFunction<R(ArgT...)>
    	: std::function<R(ArgT...)>
    {
        /**> just an alias to the type of the base class.*/
    	using Base = std::function<R(ArgT...)>;
     
    public:
        /**
        * \fn DynamicFunction(F&& f)
        * \brief pass a functor to the std::function.
        * \param F&& f : the functor to pass to the std::function.
        */
    	template<class F>
    	DynamicFunction(F&& f) : Base(std::forward<F>(f))
    	{}
    	/** \fn DynamicFunction (R (C::*pf)(ArgU...))
            *   \brief pass a pointer to a member's function to the DynamicWrapper, and then
            *   pass this wrapper to the std::function, so, the std::function call the operator() of the DynamicWrapper class
            *   and not the operator() of the std::function class so we can perform the dynamic_cast if necessary.
            *   \param R(C::*pf)(ArgU...) : the pointer to the member's function.
            *   \
            */
    	template<class C, class... ArgU>
    	DynamicFunction(R(C::*pf)(ArgU...))
    		: Base(DynamicWrapper<R,C,ArgU...>(pf))
    	{}
    	/**> just an allias to the operator() of the base class.*/
        using Base::operator();
    };
    /**
    *  \file  fastDelegate.h
    *  \class Delegate
    *  \param R the return type of the function.
    *  \brief Interface with can hold a delegate to every delegates types.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class R>
    struct Delegate {
        /**\fn Delegate()
        *  \brief default constructor.
        */
    	Delegate() =default;
    	/**\fn virtual std::unique_ptr<Delegate> clone() const = 0;
        *  \brief pure virtual function to redefine in the subclass to copy the delegate.
        *  \return std::unique_ptr<Delegate> a pointer to the copied delegate.
        */
    	virtual std::unique_ptr<Delegate> clone() const = 0;
    	/**\fn R operator()() = 0;
        *  \brief pure virtual function to redefines to call the std::function of the delegate.
        *  \return R : return the value returned by the std::function.
        */
    	//virtual R operator()() = 0;
    	/** /fn virtual Delegate()
            * \brief destructor
            */
    	virtual ~Delegate(){}
     
    protected:
        /**
        * \fn Delegate (const Delegate&) {}
        * \brief copy constructor.
        * \param const Delegate& : the delegate to copy.
        */
    	Delegate(const Delegate&){}
    	/**
        * \fn Delegate& operator= (const Delegate&) {}
        * \brief affector.
        * \return Delegate& : return a reference to the current delegate.
        */
    	Delegate& operator=(const Delegate&)
    	{
            return *this;
    	}
    };
    template <class... ArgT>
    struct RefValPl {
        template<class... ArgU>
    	RefValPl(ArgU&&... arg) :
    		param(std::forward<ArgU>(arg)...)
    	{}
        private :
        std::tuple<RefVal<ArgT, 0>...> param;
    };
    template <class... ArgT>
    struct RefValPl<Placeholder<typename ArgT::type, ArgT::i>...> {
        template<class... ArgU>
    	RefValPl(ArgU&&... arg) :
    		placeholders(std::forward<ArgU>(arg)...)
    	{}
        private :
        std::tuple<RefVal<typename ArgT::type, ArgT::i> ...>placeholders;
    };
    /**
    *  \file  fastDelegate.h
    *  \class FastDelegateImpl
    *  \brief Implementation of the delegate's interfaces.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class R, class... ArgT>
    struct FastDelegateImpl : Delegate<R> , RefValPl<ToStore_t<ArgT>...> {
        /** \fn FastDelegateImpl(F&& f, ArgU&&... arg)
        *   \brief constructor : create the delegate with the functor and the arguments value passed.
        */
    	template<class F, class... ArgU>
    	FastDelegateImpl(F&& f, ArgU&&... arg) :
    	    RefValPl<ToStore_t<ArgT>...>(arg...),
    		func(std::forward<F>(f))
    		/*, param(std::forward<ArgU>(arg)...)*/
    	{}
    	/** \fn std::unique_ptr<Delegate<R>> clone() const
        *   \brief make a copy of the delegate.
        *   \return the copied delegate.
        */
    	std::unique_ptr<Delegate<R>> clone() const
    	{ return std::make_unique<FastDelegateImpl>(*this); }
    	/** \fn R operator()()
            *   \brief call the std::function of the delegate.
        *   \return the value returned by the std::function.
        */
    	/*R operator()()
    	{ return call(std::make_index_sequence<sizeof...(ArgT)>()); }
    	/** \fn R operator()()
    	*   \brief changed the parameter's values of the std::function.
        *   \param ArgU&&... args : the values for the parameters to the delegate's function.
        */
    	/*template<class... ArgU>
    	void setParams(ArgU&&... arg)
    	{ param=std::make_tuple(std::forward<ArgU>(arg)...); }*/
     
    private:
        /** \fn R call(std::index_sequence<I...>)
            *   \brief pass each elements of the tuple to the std::function and unwarp them.
        *   \param std::index_sequence<I...> : a sequence of indexes to get every elements of the tuple.
        *   \return the value returned by the std::function.
        */
    	/*template<std::size_t... I>
    	R call(std::index_sequence<I...>)
    	{ return func(std::get<I>(param).get()...); }*/
    	DynamicFunction<R(ToStore_f<ArgT>&...)> func; /**> a functor whith hold the pointer to a callback function.*/
    	//std::tuple<RefVal<ArgT>...> param; /**> the wrapped values of the parameters to pass to the callback's function.*/
    };
    /**
    *  \file  fastDelegate.h
    *  \class FastDelegate
    *  \brief Class used for the type erasure,
    *  which allow the user be able to store a set of different callback's functions types with the same return type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class R>
    struct FastDelegate {
        /**\fn default constructor
        */
        FastDelegate() = default;
        /**\fn FastDelegate (F&& f, Arg&& arf)
        *  \param F&& f : the functor to pass.
        *  \param Arg&&... arg : arguments to pass to the functor.
        */
        template<class F, class... Arg>
    	FastDelegate(F&& f, Arg&&... arg) :
    		delegate(std::make_unique
    			<FastDelegateImpl<R, Arg...>>
    			(std::forward<F>(f), std::forward<Arg>(arg)...)
    		)
    	{}
     
    	/**\fn FastDelegate (FastDelegate& rhs)
            *  \brief copy constructor.
            *  \param FastDelegate& rhs : the delegate to copy.
            */
    	FastDelegate(FastDelegate& rhs)
    		: delegate(rhs.delegate->clone())
    	{}
    	/**\fn FastDelegate (const FastDelegate& rhs)
            *  \brief copy constructor.
            *  \param const FastDelegate& rhs : the delegate to copy.
            */
    	FastDelegate(const FastDelegate& rhs)
    		: delegate(rhs.delegate->clone())
    	{}
    	/**\fn FastDelegate (FastDelegate& rhs)
            *  \brief move constructor.
            *  \param FastDelegate&& rhs : the delegate to move.
            */
    	FastDelegate(FastDelegate&& rhs) =default;
    	/**\fn FastDelegate& operator= (FastDelegate& rhs)
            *  \brief affect the content of the delegate to the delegate.
            *  \param const FastDelegate& rhs : the delegate affect.
            *  \return FastDelegate& : the affected delegate.
            */
    	FastDelegate& operator=(const FastDelegate& rhs)
    	{ return operator=(FastDelegate(rhs)); }
    	/**\fn FastDelegate& operator= (FastDelegate& rhs)
            *  \brief affect and move the content of the delegate to the delegate.
            *  \param const FastDelegate& rhs : the delegate to move and to affect.
            *  \return FastDelegate& : the moved and affected delegate.
            */
    	FastDelegate& operator=(FastDelegate&&) =default;
    	/**\fn R operator()() const;
            *  \brief call the std::function of the delegate.
            *  \return the value returned by the std::function.
            */
    	R operator()() const
    	{ return (*delegate)(); }
    	/**\fn setParams(Arg&&... arg)
            *  \brief change the parameter's values of the delegate.
            *  \return Arg&&... arg : the values of the parameters of the delegate.
            */
    	template<class... Arg>
    	void setParams(Arg&&... arg)
    	{
    		using DynamicType =
    			FastDelegateImpl<R,ToStore_t<Arg>...>*;
    		if (dynamic_cast<DynamicType>(delegate.get()))
               dynamic_cast<DynamicType>(delegate.get())->setParams(std::forward<Arg>(arg)...);
            else
                throw odfaeg::Erreur(0, "Bad cast : you've passed a pointer to an object of a derived type as functor argument to the constructor,\n"
                             "which is not compatible with an argument of a base type passed to setParams!\n"
                             "Make a static cast from the derived object to the base object type when passing the argument to the constructor.\n"
                             "Exemple : FastDelegate<void> fd(ptrfunc, static_cast<Base*>(new Derived()); Base* b = &derived; fd.setParams(b)", 1);
    	}
    private:
    	std::unique_ptr<Delegate<R>> delegate; /**> holds the pointer to the generic delegate.*/
    };
    void f (int i) {
    }
    int main (int argv, char* argc[]) {
        FastDelegate<void>(&f, _1<int>());
        return app.exec();*/
    }

    Bon maintenant il ne me reste plus qu'à faire le get mais je ne sais pas encore comment je vais m'y prendre.

  18. #18
    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
    Ce que je propose, en entier (basé sur mon dernier code, légèrement différent du tien, mais l'idée est la même) :
    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
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
     
    //ref_val.hpp
     
    #include<functional>
    #include<memory>
     
    namespace odfaeg
    {
     
    //Type-erasure pour stocker une référence, une valeur ou un placeholder
     
    //(Interne) Interface pour la donnée du type-erasure
    template<class T>
    struct ref_val_i
    {
    	//Constructeur, destructeur
    	ref_val_i()=default;
    	virtual ~ref_val_i(){}
     
    	//Copie
    	virtual std::unique_ptr<ref_val_i> clone() const =0;
     
    	//Accès à la donnée
    	virtual T& get(void* =nullptr, void* =nullptr) =0;
     
    protected:
    	ref_val_i(const ref_val_i&){}
     
    	ref_val_i& operator=(const ref_val_i&)
    	{ return *this; }
    };
     
    //(Interne) Donnée de type référence
    template<class T>
    struct ref : ref_val_i<T>
    {
    	ref(const std::reference_wrapper<T>& r)
    		: data(r)
    	{}
     
    	std::unique_ptr<ref_val_i<T>> clone() const
    	{ return std::make_unique<ref>(*this); }
     
    	T& get(void*, void*)
    	{ return data.get(); }
     
    private:
    	std::reference_wrapper<T> data;
    };
     
    //Donnée de type placeholder
    template<size_t I, class T>
    struct ph;
     
    template<class T>
    struct ph<1,T> : ref_val_i<T>
    {
    	std::unique_ptr<ref_val_i<T>> clone() const
    	{ return std::make_unique<ph>(*this); }
     
    	T& get(void* p, void*)
    	{ return *static_cast<T*>(p); }
    };
     
    template<class T>
    struct ph<2,T> : ref_val_i<T>
    {
    	std::unique_ptr<ref_val_i<T>> clone() const
    	{ return std::make_unique<ph>(*this); }
     
    	T& get(void*, void* p)
    	{ return *static_cast<T*>(p); }
    };
     
    //(Interne) Donnée de type valeur
    template<class T>
    struct val : ref_val_i<T>
    {
    	template<class U>
    	val(U&& t)
    		: data(std::forward<U>(t))
    	{}
     
    	std::unique_ptr<ref_val_i<T>> clone() const
    	{ return std::make_unique<val>(*this); }
     
    	T& get(void*,void*)
    	{ return data; }
     
    private:
    	T data;
    };
     
    //(Utilisateur) Classe métier du type-erasure
    template<class T>
    struct ref_val
    {
    	template<class U>
    	ref_val(U&& t)
    		: rv(std::make_unique<val<T>>(std::forward<U>(t)))
    	{}
    	ref_val(const std::reference_wrapper<T>& r)
    		: rv(std::make_unique<ref<T>>(r))
    	{}
    	ref_val(std::reference_wrapper<T>& r)
    		: rv(std::make_unique<ref<T>>(r))
    	{}
    	ref_val(std::reference_wrapper<T>&& r)
    		: rv(std::make_unique<ref<T>>(r))
    	{}
    	template<size_t I>
    	ref_val(ph<I,T>&&)
    		: rv(std::make_unique<ph<I,T>>())
    	{}
    	ref_val(const ref_val& rhs)
    		: rv(rhs.rv->clone())
    	{}
     
    	ref_val& operator=(const ref_val& rhs)
    	{ rv=rhs.rv->clone(); return *this; }
     
    	template<class... Arg>
    	T& get(Arg... arg) const
    	{ return rv->get(arg...); }
     
    private:
    	std::unique_ptr<ref_val_i<T>> rv;
    };
     
    }
     
    //to_store.hpp
     
    #include<functional>
    #include<type_traits>
     
    namespace odfaeg
    {
     
    //Classe de trait pour déterminer le type à stocker
     
    //(Interne) Cas général
    template<class T>
    struct to_store_impl
    { using type = T; };
     
    //(Interne) Spécilisation pour les références
    template<class T>
    struct to_store_impl<std::reference_wrapper<T>>
    { using type = T; };
     
    //(Interne) Spécilisation pour les placeholders
    template<size_t I, class T>
    struct to_store_impl<ph<I,T>>
    { using type = T; };
     
    //(Utilisateur) Classe de trait
    template<class T>
    struct to_store
    	: to_store_impl<std::decay_t<T>>
    {};
     
    //(Utilisateur) Alias pour la classe de trait
    template<class T>
    using to_store_t = typename
    	to_store<T>::type;
     
    }
     
    //delegate.hpp
     
    #include<memory>
     
    #include<boost/mpl/apply.hpp>
    #include<boost/mpl/if.hpp>
    #include<boost/mpl/placeholders.hpp>
     
    //#include"function_dyn.hpp"
    //#include"ref_val.hpp"
    //#include"to_store.hpp"
     
    namespace odfaeg
    {
     
    namespace mpl = boost::mpl;
     
    using mpl::placeholders::_;
     
    //Système de callback incluant un stockage des paramètres
     
    //(Interne) Classe interface pour le type-erasure
    template<class R>
    struct delegate_i
    {
    	delegate_i() =default;
    	virtual ~delegate_i(){}
     
    	virtual std::unique_ptr<delegate_i> clone() const =0;
     
    	virtual R operator()(void* =nullptr, void* =nullptr) const = 0;
     
    protected:
    	delegate_i(const delegate_i&){}
     
    	delegate_i& operator=(const delegate_i&)
    	{ return *this; }
    };
     
    //(Interne) Classe générique d'implémentation du type-erasure
    template<class PFun, class R, class... ArgT>
    struct delegate_impl : delegate_i<R>
    {
    	template<class F, class... ArgU>
    	delegate_impl(F&& f, ArgU&&... arg)
    		: func(std::forward<F>(f))
    		, param(std::forward<ArgU>(arg)...)
    	{}
     
    	std::unique_ptr<delegate_i<R>> clone() const
    	{ return std::make_unique<delegate_impl>(*this); }
     
    	R operator()(void* p1, void* p2) const
    	{ return call(std::make_index_sequence<sizeof...(ArgT)>(),p1,p2); }
    	template<class... ArgU>
    	void set(ArgU&&... arg)
    	{ param=std::make_tuple(std::forward<ArgU>(arg)...); }
     
    private:
    	template<std::size_t... I, class... ArgU>
    	R call(std::index_sequence<I...>, ArgU... arg) const
    	{ return func(std::get<I>(param).get(arg...)...); }
     
    	typename mpl::apply<
    		PFun,R(ArgT&...)
    	>::type func;
    	std::tuple<ref_val<ArgT>...> param;
    };
     
    //(Utilisateur) Classe métier du système
    template<
    	class R,
    	class PFun =function_dyn<_>,
    	class PConv =mpl::if_<
    		std::is_same<std::decay<_>,const char*>,
    		std::string,_
    	>
    >
    struct delegate {
    	template<class F, class... Arg>
    	delegate(F&& f, Arg&&... arg) :
    		data(std::make_unique<delegate_impl<
    				PFun,R,
    				typename mpl::apply<to_store<PConv>,Arg>::type...
    			>>
    			(std::forward<F>(f),std::forward<Arg>(arg)...)
    		)
    	{}
    	delegate(const delegate& rhs)
    		: data(rhs.data->clone())
    	{}
    	delegate(delegate& rhs)
    		: data(rhs.data->clone())
    	{}
    	delegate(delegate&& rhs) =default;
     
    	delegate& operator=(const delegate& rhs)
    	{ return operator=(delegate(rhs)); }
    	delegate& operator=(delegate&&) =default;
     
    	template<class... Arg>
    	R operator()(Arg&&... arg) const
    	{ return (*data)(&arg...); }
    	template<class... Arg>
    	void set(Arg&&... arg)
    	{
    		using DynamicType = delegate_impl<
    			PFun,R,
    			typename mpl::apply<to_store<PConv>,Arg>::type...
    		>*;
     
    		if(dynamic_cast<DynamicType>(data.get()))
    			dynamic_cast<DynamicType>(data.get())->set(std::forward<Arg>(arg)...);
    	}
     
    private:
    	std::unique_ptr<delegate_i<R>> data;
    };
     
    }
     
    #include<iostream>
    #include<string>
     
    void foo(int i)
    { std::cout << i; }
     
    int main(){
    	odfaeg::delegate<void> func(foo,odfaeg::ph<1,int>());
    	func(1);
    	std::cout << std::endl;
    }
    Temps de code : moins de quinze minute. Il faut rajouter des mécanismes de sécurité (assertion) et automatiser la génération pour N placeholder (boost.pp fortement recommandé pour).

  19. #19
    Invité
    Invité(e)
    Par défaut
    Oui sauf que moi j'ai pas besoin de boost pp.

    Par contre je ne comprend pas pourquoi le compilateur ne me choisis pas la spécialisation avec les placeholders 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
    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
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    540
    541
    542
    543
    544
    545
    546
    547
    548
    549
    550
    551
    552
    553
    554
    555
    556
    557
    558
    559
    560
    561
    562
    563
    564
    565
    566
    567
    568
    569
    570
    571
    572
    573
    574
    575
    576
    577
    578
    579
    580
    581
    582
    583
    584
    585
    586
    587
    588
    589
    590
    591
    592
    593
    594
    595
    596
    597
    598
    599
    600
    601
    602
    603
    604
    605
    606
    607
    608
    609
    610
    611
    612
    613
    614
    615
    616
    617
    618
    619
    620
    621
    622
    623
    624
    625
    626
    627
    628
    629
    630
    631
    632
    633
    634
    635
    636
    637
    638
    639
    640
    641
    642
    643
    644
    645
    646
    647
    648
    649
    650
    651
    652
    653
    654
    655
    656
    657
    658
    659
    660
    661
    662
    663
    664
    665
    666
    667
    668
    669
    670
    671
    672
    673
    674
    675
    676
    677
    678
    679
    680
    681
    682
    683
    684
    685
    686
    687
    688
    689
    690
    691
    692
    693
    694
    695
    696
    697
    698
    699
     
    //#include "application.h"
    #include <fstream>
    #include "odfaeg/Core/fastDelegate.h"
    #include <functional>
    #include <iostream>
    #include <tuple>
    #include <utility>
    #include <memory>
    #include "../include/odfaeg/Core/erreur.h"
    /**
    *  \file  fastDelegate.h
    *  \class IRefVal
    *  \brief Interface for the warppers to references, values and pointers.
    *  This class is used store references, pointers and values to pass to the callack's functions.
    *  \param T : the type of the value to wrap.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template <class T, int I>
    struct Placeholder {
        static constexpr int i = I;
        using type = T;
    };
    template <class T>
    using _1 = Placeholder<T, 1>;
    template <class T>
    using _2 = Placeholder<T, 2>;
    template <typename T>
    struct is_placeholder {
        static constexpr bool value = false;
    };
    template <typename T, int I>
    struct is_placeholder<Placeholder<T, I>> {
        static constexpr bool value = true;
    };
    template <typename T, int I>
    struct IRefVal {
        /**\fn
        *  \brief default constructor
        */
    	IRefVal()=default;
    	/**\fn T& get()
            *  \brief get the reference of the wrapped type.
            *  \return the reference of the wrapped type.
            */
    	virtual Placeholder<T, I>& get() =0;
    	/**\fn std::unique_ptr<IRefVal<T>> clone() const = 0;
            *  \brief copy the wrapper.
            *  \return the copied wrapper.*/
    	virtual std::unique_ptr<IRefVal<T, I>> clone() const = 0;
    	/**\fn destructor*/
    	virtual ~IRefVal(){}
     
    protected:
        /**\fn IRefVal(const IRefVal&)
        *  \brief constructor, pass the reference to wrap.
        *  \param const IRefVal& : the reference to wrap.
        */
    	IRefVal(const IRefVal&){}
    	/** \fn IRefVal& operator=(const IRefVal&)
            *   \brief affector.
            *   \param const IRefVal& : the wrapper to affect.
            *   \return the affected wrapper.*/
    	IRefVal& operator=(const IRefVal&)
    	{ return *this; }
    };
    template<class T>
    struct IRefVal<T, 0> {
        /**\fn
        *  \brief default constructor
        */
    	IRefVal()=default;
    	/**\fn T& get()
            *  \brief get the reference of the wrapped type.
            *  \return the reference of the wrapped type.
            */
    	virtual T& get() =0;
    	/**\fn std::unique_ptr<IRefVal<T>> clone() const = 0;
            *  \brief copy the wrapper.
            *  \return the copied wrapper.*/
    	virtual std::unique_ptr<IRefVal<T, 0>> clone() const = 0;
    	/**\fn destructor*/
    	virtual ~IRefVal(){}
     
    protected:
        /**\fn IRefVal(const IRefVal&)
        *  \brief constructor, pass the reference to wrap.
        *  \param const IRefVal& : the reference to wrap.
        */
    	IRefVal(const IRefVal&){}
    	/** \fn IRefVal& operator=(const IRefVal&)
            *   \brief affector.
            *   \param const IRefVal& : the wrapper to affect.
            *   \return the affected wrapper.*/
    	IRefVal& operator=(const IRefVal&)
    	{ return *this; }
    };
    /**
    *  \file  fastDelegate.h
    *  \class Ref
    *  \brief Warp a reference. (Use std::reference_wrapper so we can pass a reference with std::ref)
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    struct Ref : IRefVal<T, 0> {
        /**
        *\fn Ref(const std::reference_wrapper<T>& r)
        *\brief Constructor : pass an std::reference_wrapper to the wrapper.
        *\param std::reference_wrapper<T>& r : the reference_wrapper.
        */
    	Ref(const std::reference_wrapper<T>& r)
    		: ref(r)
    	{}
    	/**
            * \fn T& get()
            * \brief return a reference to an object.
            * \return T& the reference to the object.
            */
    	T& get()
    	{ return ref.get(); }
    	/**
            * \fn std::unique_ptr<IRefVal<T>> clone() const
            * \brief copy the reference wrapper.
            * \return std::unique_ptr<IRefVal<T>> : the cloned wrapper.
            */
    	std::unique_ptr<IRefVal<T, 0>> clone() const
    	{ return std::make_unique<Ref>(*this); }
    private:
    	std::reference_wrapper<T> ref; /**> the std::reference_wrapper which warp the reference.*/
    };
    /**
    *  \file  fastDelegate.h
    *  \class Val
    *  \brief Warp a value.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    struct Val : IRefVal<T, 0> {
        /**\fn Val(const T& t)
        *  \brief pass a value to the wrapper.
        *  \param const T& t : the value to pass.
        */
    	Val(const T& t)
    		: val(t)
    	{}
    	/** \fn
            *   \brief return the value
            *   \return T& : return the value.
            */
    	T& get()
    	{ return val; }
     
    	/**
            * \fn std::unique_ptr<IRefVal<T>> clone() const
            * \brief copy the value wrapper.
            * \return std::unique_ptr<IRefVal<T>> : the cloned wrapper.
            */
    	std::unique_ptr<IRefVal<T, 0>> clone() const
    	{ return std::make_unique<Val>(*this); }
    private:
    	T val; /**> T val : keep the value of the wrapper.*/
    };
    template <class T, int I>
    struct PlaceholdersWrapper : IRefVal<T, I> {
         PlaceholdersWrapper (Placeholder<T, I> pl) : pl(pl) {
     
         }
         Placeholder<T, I>& get() {
             return pl;
         }
         std::unique_ptr<IRefVal<T, I>> clone() const
    	 { return std::make_unique<PlaceholdersWrapper<T, I>>(*this); }
    private :
         Placeholder<T, I> pl;
    };
    /**
    *  \file  fastDelegate.h
    *  \class Ref
    *  \brief Warp a pointer.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T, int I>
    struct RefVal {
        RefVal() = default;
        RefVal(const Placeholder<T, I>& pl)
    	: rv(std::make_unique<PlaceholdersWrapper<T, I>>(pl))
    	{}
    	RefVal(const RefVal& rhs) {
    	    rv = rhs.rv->clone();
    	}
    	RefVal& operator=(const RefVal& rhs)
    	{ rv=rhs.rv->clone(); return *this; }
    	/** \fn T& get() const
            *   \brief get the wrapper.
            *   \return a unique pointer to the generic wrapper interface.
            */
    	Placeholder<T, I>& get() const
    	{ return rv->get(); }
    private:
    	std::unique_ptr<IRefVal<T, I>> rv; /**> a pointer to the generic wrapper interface.*/
    };
    template<class T>
    struct RefVal<T, 0> {
        RefVal() = default;
        /**
        * \fn RefVal (const T& t)
        * \brief constructor : construct a wrapper to a value
        * \param const T& t : the value to
        */
    	RefVal(const T& t)
    	: rv(std::make_unique<Val<T>>(t))
    	{}
    	/**
        * \fn RefVal (const std::reference_wrapper<T>& r)
        * \brief constructor : construct a wrapper to an std::reference_wrapper.
        * \param const std::reference_wrapper<T>& : the std::reference_wrapper to pass.
        */
    	RefVal(const std::reference_wrapper<T>& r)
    	: rv(std::make_unique<Ref<T>>(r))
    	{}
    	RefVal(const RefVal& rhs) {
    	    rv = rhs.rv->clone();
    	}
    	RefVal(const RefVal&& rhs) {
            rv = rhs.rv->clone();
    	}
    	RefVal& operator=(const RefVal& rhs)
    	{ rv=rhs.rv->clone(); return *this; }
    	RefVal& operator=(const RefVal&& rhs)
    	{ rv=rhs.rv->clone(); return *this; }
    	T& get() {
    	    return rv->get();
    	}
    	/** \fn T& get() const
            *   \brief get the wrapper.
            *   \return a unique pointer to the generic wrapper interface.
            */
    private:
    	std::unique_ptr<IRefVal<T, 0>> rv; /**> a pointer to the generic wrapper interface.*/
    };
    //Classe de trait pour déterminer le type à stocker
     
    //(Interne) Cas général
    /**
    *  \file  fastDelegate.h
    *  \class ToStoreImpl
    *  \param T the type of the wrapper.
    *  \brief Trait class which use an alias on a wrapped type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    struct ToStoreImpl1
    { using type = T; };
    /**
    *  \file  fastDelegate.h
    *  \class ToStoreImpl
    *  \param T the type warpped in the warpper.
    *  \brief Trait class with keep an alias on the wrapped type.
    *  This class is specialized for std::_reference_wrapper type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    struct ToStoreImpl1<std::reference_wrapper<T>>
    { using type = T; };
    template<class T, int I>
    struct ToStoreImpl1<Placeholder<T, I>>
    { using type = T; };
     
    /**
    *  \file  fastDelegate.h
    *  \class ToStore
    *  \param T the type of the wrapper.
    *  \brief Trait class with keep an alias of the wrapper type. (without the reference)
    *  the inheritance use the right specialized templated class to hold the type of the wrapped object
    *  depending on the wrapper type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    struct ToStore1
    	: ToStoreImpl1<std::remove_reference_t<T>>
    {};
    /**
    *  \file  fastDelegate.h
    *  \class ToStore_t
    *  \param T the type of the wrapped object.
    *  \brief Trait class which hold an alias to the real type of the wrapped type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    using ToStore_f = typename
    	ToStore1<T>::type;
    //Classe de trait pour déterminer le type à stocker
     
    //(Interne) Cas général
    /**
    *  \file  fastDelegate.h
    *  \class ToStoreImpl
    *  \param T the type of the wrapper.
    *  \brief Trait class which use an alias on a wrapped type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    struct ToStoreImpl2
    { using type = T; };
    /**
    *  \file  fastDelegate.h
    *  \class ToStoreImpl
    *  \param T the type warpped in the warpper.
    *  \brief Trait class with keep an alias on the wrapped type.
    *  This class is specialized for std::_reference_wrapper type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    struct ToStoreImpl2<std::reference_wrapper<T>>
    { using type = T; };
    template<class T, int I>
    struct ToStoreImpl2<Placeholder<T, I>>
    { using type = Placeholder<T, I>; };
     
    /**
    *  \file  fastDelegate.h
    *  \class ToStore
    *  \param T the type of the wrapper.
    *  \brief Trait class with keep an alias of the wrapper type. (without the reference)
    *  the inheritance use the right specialized templated class to hold the type of the wrapped object
    *  depending on the wrapper type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    struct ToStore2
    	: ToStoreImpl2<std::remove_reference_t<T>>
    {};
    /**
    *  \file  fastDelegate.h
    *  \class ToStore_t
    *  \param T the type of the wrapped object.
    *  \brief Trait class which hold an alias to the real type of the wrapped type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class T>
    using ToStore_t = typename
    	ToStore2<T>::type;
    /**
    *  \file  fastDelegate.h
    *  \class DynamicWrapper
    *  \param R the return type of the wrapped functor.
    *  \param C the class type of the wrapped functor.
    *  \param ArgT the arguments types of the wrapped functor.
    *  \brief This class warp a function pointer to a member function.
    *  I don't use an std::function directly here to keep the class type of the member function pointer
    *  because if the passed object is polymorphic, I need to apply a dynamic cast
    *  before calling the member function pointer on the object.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class R, class C, class... ArgT>
    struct DynamicWrapper {
        /**\fn DynamicWrapper(R(C::*pf)(ArgT...)) : pfunc(pf)
        *  \brief warp a pointer to a member function.
        *  \param R(C::*pf)(ArgT...) : the pointer to the member function.
        */
    	DynamicWrapper(R(C::*pf)(ArgT...)) : pfunc(pf){}
    	/**\fn R operator()(O* o, ArgU&&... arg) const
            *  \brief call the member function's pointer witht he given object and the given argument
            *  apply a dynamic_cast in case of the type of the object and the type of the classe containing the member function
            *  are not the same. (If the object is polymoprhic)
            *  If the cast fails it means that the object is not polymorphic so it throws an error.
            *  \param O* o : the object onwich to call the member function's pointer.
            *  \param ArgU&& arg : the arguments of the member function's pointer to call.
            */
    	template<class O, class... ArgU>
    	R operator()(O* o, ArgU&&... arg) const
    	{
    	    if(dynamic_cast<C*>(o))
    			return (dynamic_cast<C*>(o)->*pfunc)(std::forward<ArgU>(arg)...);
            throw odfaeg::Erreur(0, "Invalid cast : types are nor polymorphic!", 1);
    	}
    	template<class O, class... ArgU>
    	R operator()(O& o, ArgU&&... arg) const
    	{
    		if(dynamic_cast<C&>(o))
    			return (dynamic_cast<C&>(o).*pfunc)(std::forward<ArgU>(arg)...);
            throw odfaeg::Erreur(0, "Invalid cast : types are nor polymorphic!", 1);
    	}
    private:
    	R (C::*pfunc)(ArgT...); /**> a pointer to a member's function.*/
    };
    /**
    *  \file  fastDelegate.h
    *  \class DynamicFunction
    *  \param F the type of the function.
    *  \brief Generic class for every functors type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class F>
    class DynamicFunction;
    /**
    *  \file  fastDelegate.h
    *  \class DynamicFunction
    *  \param R the return type of the function.
    *  \param ArgT... the type of the arguments of the function.
    *  \brief Specialized template class for functors. (inherit from std::function)
    *  build a functor with the right constructor depending a the pointer's function type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class R, class... ArgT>
    class DynamicFunction<R(ArgT...)>
    	: std::function<R(ArgT...)>
    {
        /**> just an alias to the type of the base class.*/
    	using Base = std::function<R(ArgT...)>;
     
    public:
        /**
        * \fn DynamicFunction(F&& f)
        * \brief pass a functor to the std::function.
        * \param F&& f : the functor to pass to the std::function.
        */
    	template<class F>
    	DynamicFunction(F&& f) : Base(std::forward<F>(f))
    	{}
    	/** \fn DynamicFunction (R (C::*pf)(ArgU...))
            *   \brief pass a pointer to a member's function to the DynamicWrapper, and then
            *   pass this wrapper to the std::function, so, the std::function call the operator() of the DynamicWrapper class
            *   and not the operator() of the std::function class so we can perform the dynamic_cast if necessary.
            *   \param R(C::*pf)(ArgU...) : the pointer to the member's function.
            *   \
            */
    	template<class C, class... ArgU>
    	DynamicFunction(R(C::*pf)(ArgU...))
    		: Base(DynamicWrapper<R,C,ArgU...>(pf))
    	{}
    	/**> just an allias to the operator() of the base class.*/
        using Base::operator();
    };
    /**
    *  \file  fastDelegate.h
    *  \class Delegate
    *  \param R the return type of the function.
    *  \brief Interface with can hold a delegate to every delegates types.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class R>
    struct Delegate {
        /**\fn Delegate()
        *  \brief default constructor.
        */
    	Delegate() =default;
    	/**\fn virtual std::unique_ptr<Delegate> clone() const = 0;
        *  \brief pure virtual function to redefine in the subclass to copy the delegate.
        *  \return std::unique_ptr<Delegate> a pointer to the copied delegate.
        */
    	virtual std::unique_ptr<Delegate> clone() const = 0;
    	/**\fn R operator()() = 0;
        *  \brief pure virtual function to redefines to call the std::function of the delegate.
        *  \return R : return the value returned by the std::function.
        */
    	//virtual R operator()() = 0;
    	/** /fn virtual Delegate()
            * \brief destructor
            */
    	virtual ~Delegate(){}
     
    protected:
        /**
        * \fn Delegate (const Delegate&) {}
        * \brief copy constructor.
        * \param const Delegate& : the delegate to copy.
        */
    	Delegate(const Delegate&){}
    	/**
        * \fn Delegate& operator= (const Delegate&) {}
        * \brief affector.
        * \return Delegate& : return a reference to the current delegate.
        */
    	Delegate& operator=(const Delegate&)
    	{
            return *this;
    	}
    };
    template <class... ArgT>
    struct RefValPl {
        template<class... ArgU>
    	RefValPl(ArgU&&... arg) :
    		param(std::forward<ArgU>(arg)...)
    	{
    	    std::cout<<"non place holder"<<std::endl;
    	}
    	template <typename... ArgU>
    	void setParams(ArgU&&... args) {
            param = std::make_tuple(std::forward<ArgU>(args)...);
    	}
    	std::tuple<RefVal<ArgT, 0>...> getParams() {
    	    return param;
    	}
        private :
        std::tuple<RefVal<ArgT, 0>...> param;
    };
    template <class... ArgT>
    struct RefValPl<Placeholder<typename ArgT::type, ArgT::I>...> {
        template<class... ArgU>
    	RefValPl(ArgU&&... arg) :
    		 placeholders(std::forward<ArgU>(arg)...)
    	{
    	    std::cout<<"place holder"<<std::endl;
    	}
    	template <typename... ArgU>
    	void setParams(ArgU&&... args) {
    	    std::tuple<ArgU...> tp = std::make_tuple(std::forward<ArgU>(args)...);
            changeParams(std::make_index_sequence<sizeof...(ArgT)>(), tp);
    	}
    	std::tuple<RefVal<typename ArgT::type, ArgT::i>...> getParams() {
    	   return param;
    	}
        private :
        template <std::size_t... IND, typename... ArgU>
        void changeParams (std::index_sequence<IND...>, std::tuple<ArgU...> tp) {
            param = std::make_tuple(std::get<IND>(tp)...);
        }
        std::tuple<RefVal<typename ArgT::type, ArgT::i>...> placeholders;
        std::tuple<RefVal<typename ArgT::type, 0>...> param;
    };
    /**
    *  \file  fastDelegate.h
    *  \class FastDelegateImpl
    *  \brief Implementation of the delegate's interfaces.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class R, class... ArgT>
    struct FastDelegateImpl : Delegate<R> , RefValPl<ToStore_t<ArgT>...> {
        /** \fn FastDelegateImpl(F&& f, ArgU&&... arg)
        *   \brief constructor : create the delegate with the functor and the arguments value passed.
        */
    	template<class F, class... ArgU>
    	FastDelegateImpl(F&& f, ArgU&&... arg) :
    	    RefValPl<ToStore_t<ArgT>...>(std::forward<ArgU>(arg)...),
    		func(std::forward<F>(f))
    		/*, param(std::forward<ArgU>(arg)...)*/
    	{}
    	/** \fn std::unique_ptr<Delegate<R>> clone() const
        *   \brief make a copy of the delegate.
        *   \return the copied delegate.
        */
    	std::unique_ptr<Delegate<R>> clone() const
    	{ return std::make_unique<FastDelegateImpl>(*this); }
    	/** \fn R operator()()
            *   \brief call the std::function of the delegate.
        *   \return the value returned by the std::function.
        */
        template <typename... ArgU>
    	void setParams(ArgU&&... args) {
    	    RefValPl<ToStore_t<ArgT>...>::setParams(std::forward<ArgU...>(args)...);
    	}
    	/*R operator()()
    	{ return call(std::make_index_sequence<sizeof...(ArgT)>()); }
    	/** \fn R operator()()
    	*   \brief changed the parameter's values of the std::function.
        *   \param ArgU&&... args : the values for the parameters to the delegate's function.
        */
    	/*template<class... ArgU>
    	void setParams(ArgU&&... arg)
    	{ param=std::make_tuple(std::forward<ArgU>(arg)...); }*/
     
    private:
        /** \fn R call(std::index_sequence<I...>)
            *   \brief pass each elements of the tuple to the std::function and unwarp them.
        *   \param std::index_sequence<I...> : a sequence of indexes to get every elements of the tuple.
        *   \return the value returned by the std::function.
        */
    	/*template<std::size_t... I>
    	R call(std::index_sequence<I...>)
    	{ return func(std::get<I>(param).get()...); }*/
    	DynamicFunction<R(ToStore_f<ArgT>&...)> func; /**> a functor whith hold the pointer to a callback function.*/
    	//std::tuple<RefVal<ArgT>...> param; /**> the wrapped values of the parameters to pass to the callback's function.*/
    };
    /**
    *  \file  fastDelegate.h
    *  \class FastDelegate
    *  \brief Class used for the type erasure,
    *  which allow the user be able to store a set of different callback's functions types with the same return type.
    *  \author Duroisin.L
    *  \version 1.0
    *  \date 1/02/2014
    */
    template<class R>
    struct FastDelegate {
        /**\fn default constructor
        */
        FastDelegate() = default;
        /**\fn FastDelegate (F&& f, Arg&& arf)
        *  \param F&& f : the functor to pass.
        *  \param Arg&&... arg : arguments to pass to the functor.
        */
        template<class F, class... Arg>
    	FastDelegate(F&& f, Arg&&... arg) :
    		delegate(std::make_unique
    			<FastDelegateImpl<R, Arg...>>
    			(std::forward<F>(f), std::forward<Arg>(arg)...)
    		)
    	{}
     
    	/**\fn FastDelegate (FastDelegate& rhs)
            *  \brief copy constructor.
            *  \param FastDelegate& rhs : the delegate to copy.
            */
    	FastDelegate(FastDelegate& rhs)
    		: delegate(rhs.delegate->clone())
    	{}
    	/**\fn FastDelegate (const FastDelegate& rhs)
            *  \brief copy constructor.
            *  \param const FastDelegate& rhs : the delegate to copy.
            */
    	FastDelegate(const FastDelegate& rhs)
    		: delegate(rhs.delegate->clone())
    	{}
    	/**\fn FastDelegate (FastDelegate& rhs)
            *  \brief move constructor.
            *  \param FastDelegate&& rhs : the delegate to move.
            */
    	FastDelegate(FastDelegate&& rhs) =default;
    	/**\fn FastDelegate& operator= (FastDelegate& rhs)
            *  \brief affect the content of the delegate to the delegate.
            *  \param const FastDelegate& rhs : the delegate affect.
            *  \return FastDelegate& : the affected delegate.
            */
    	FastDelegate& operator=(const FastDelegate& rhs)
    	{ return operator=(FastDelegate(rhs)); }
    	/**\fn FastDelegate& operator= (FastDelegate& rhs)
            *  \brief affect and move the content of the delegate to the delegate.
            *  \param const FastDelegate& rhs : the delegate to move and to affect.
            *  \return FastDelegate& : the moved and affected delegate.
            */
    	FastDelegate& operator=(FastDelegate&&) =default;
    	/**\fn R operator()() const;
            *  \brief call the std::function of the delegate.
            *  \return the value returned by the std::function.
            */
    	R operator()() const
    	{ return (*delegate)(); }
    	/**\fn setParams(Arg&&... arg)
            *  \brief change the parameter's values of the delegate.
            *  \return Arg&&... arg : the values of the parameters of the delegate.
            */
    	template<class... ArgT, class... ArgV>
    	void setParams(ArgV&&... arg)
    	{
    		using DynamicType =
    			FastDelegateImpl<R, ArgT...>*;
    		if (dynamic_cast<DynamicType>(delegate.get()))
               dynamic_cast<DynamicType>(delegate.get())->setParams(std::forward<ArgV>(arg)...);
            else
                throw odfaeg::Erreur(0, "Bad cast : you've passed a pointer to an object of a derived type as functor argument to the constructor,\n"
                             "which is not compatible with an argument of a base type passed to setParams!\n"
                             "Make a static cast from the derived object to the base object type when passing the argument to the constructor.\n"
                             "Exemple : FastDelegate<void> fd(ptrfunc, static_cast<Base*>(new Derived()); Base* b = &derived; fd.setParams(b)", 1);
    	}
    private:
    	std::unique_ptr<Delegate<R>> delegate; /**> holds the pointer to the generic delegate.*/
    };
    void f (int i) {
    }
    int main (int argv, char* argc[]) {
        FastDelegate<void> fd(&f, _1<int>());
        //fd.setParams<_1<int>>(1);   
        return app.exec();*/
    }

  20. #20
    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 n'utilise pas boost.pp actuellement, son utilisation c'est pour éviter la répétition de code. Quoiqu'il en soit, le code est là pour te montrer le mécanisme à mettre en place pour répondre à ta problématique (et je suis presque certain qu'il n'y a pas d'alternative fondamentalement différente). J'ai pu gérer la répétition sans boost.pp en factorisant une partie du code :
    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
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
     
    //ref_val.hpp
     
    #include<functional>
    #include<memory>
     
    #define FUN_PARAM void* p0 =nullptr, void* p1 =nullptr, void* p2 =nullptr, void* p3 =nullptr
    #define FWD_PARAM p0,p1,p2,p3
     
    namespace odfaeg
    {
     
    //Type-erasure pour stocker une référence, une valeur ou un placeholder
     
    //(Interne) Interface pour la donnée du type-erasure
    template<class T>
    struct ref_val_i
    {
    	//Constructeur, destructeur
    	ref_val_i()=default;
    	virtual ~ref_val_i(){}
     
    	//Copie
    	virtual std::unique_ptr<ref_val_i> clone() const =0;
     
    	//Accès à la donnée
    	virtual T& get(FUN_PARAM) =0;
     
    protected:
    	ref_val_i(const ref_val_i&){}
     
    	ref_val_i& operator=(const ref_val_i&)
    	{ return *this; }
    };
     
    //(Interne) Donnée de type référence
    template<class T>
    struct ref : ref_val_i<T>
    {
    	ref(const std::reference_wrapper<T>& r)
    		: data(r)
    	{}
     
    	std::unique_ptr<ref_val_i<T>> clone() const
    	{ return std::make_unique<ref>(*this); }
     
    	T& get(FUN_PARAM)
    	{ return data.get(); }
     
    private:
    	std::reference_wrapper<T> data;
    };
     
    //Donnée de type placeholder
    template<size_t I, class T>
    struct ph : ref_val_i<T>
    {
    	std::unique_ptr<ref_val_i<T>> clone() const
    	{ return std::make_unique<ph>(*this); }
     
    	T& get(FUN_PARAM)
    	{
    		return *static_cast<T*>
    			(std::get<I>(std::make_tuple(FWD_PARAM)));
    	}
    };
     
    //(Interne) Donnée de type valeur
    template<class T>
    struct val : ref_val_i<T>
    {
    	template<class U>
    	val(U&& t)
    		: data(std::forward<U>(t))
    	{}
     
    	std::unique_ptr<ref_val_i<T>> clone() const
    	{ return std::make_unique<val>(*this); }
     
    	T& get(FUN_PARAM)
    	{ return data; }
     
    private:
    	T data;
    };
     
    //(Utilisateur) Classe métier du type-erasure
    template<class T>
    struct ref_val
    {
    	template<class U>
    	ref_val(U&& t)
    		: rv(std::make_unique<val<T>>(std::forward<U>(t)))
    	{}
    	ref_val(const std::reference_wrapper<T>& r)
    		: rv(std::make_unique<ref<T>>(r))
    	{}
    	ref_val(std::reference_wrapper<T>& r)
    		: rv(std::make_unique<ref<T>>(r))
    	{}
    	ref_val(std::reference_wrapper<T>&& r)
    		: rv(std::make_unique<ref<T>>(r))
    	{}
    	template<size_t I>
    	ref_val(ph<I,T>&&)
    		: rv(std::make_unique<ph<I,T>>())
    	{}
    	ref_val(const ref_val& rhs)
    		: rv(rhs.rv->clone())
    	{}
     
    	ref_val& operator=(const ref_val& rhs)
    	{ rv=rhs.rv->clone(); return *this; }
     
    	template<class... Arg>
    	T& get(Arg&&... arg) const
    	{ return rv->get(std::forward<Arg>(arg)...); }
     
    private:
    	std::unique_ptr<ref_val_i<T>> rv;
    };
     
    }
     
    //to_store.hpp
     
    #include<functional>
    #include<type_traits>
     
    namespace odfaeg
    {
     
    //Classe de trait pour déterminer le type à stocker
     
    //(Interne) Cas général
    template<class T>
    struct to_store_impl
    { using type = T; };
     
    //(Interne) Spécilisation pour les références
    template<class T>
    struct to_store_impl<std::reference_wrapper<T>>
    { using type = T; };
     
    //(Interne) Spécilisation pour les placeholders
    template<size_t I, class T>
    struct to_store_impl<ph<I,T>>
    { using type = T; };
     
    //(Utilisateur) Classe de trait
    template<class T>
    struct to_store
    	: to_store_impl<std::decay_t<T>>
    {};
     
    //(Utilisateur) Alias pour la classe de trait
    template<class T>
    using to_store_t = typename
    	to_store<T>::type;
     
    }
     
    //delegate.hpp
     
    #include<memory>
     
    #include<boost/mpl/apply.hpp>
    #include<boost/mpl/if.hpp>
    #include<boost/mpl/placeholders.hpp>
     
    //#include"function_dyn.hpp"
    //#include"ref_val.hpp"
    //#include"to_store.hpp"
     
    namespace odfaeg
    {
     
    namespace mpl = boost::mpl;
     
    using mpl::placeholders::_;
     
    //Système de callback incluant un stockage des paramètres
     
    //(Interne) Classe interface pour le type-erasure
    template<class R>
    struct delegate_i
    {
    	delegate_i() =default;
    	virtual ~delegate_i(){}
     
    	virtual std::unique_ptr<delegate_i> clone() const =0;
     
    	virtual R operator()(FUN_PARAM) const = 0;
     
    protected:
    	delegate_i(const delegate_i&){}
     
    	delegate_i& operator=(const delegate_i&)
    	{ return *this; }
    };
     
    //(Interne) Classe générique d'implémentation du type-erasure
    template<class PFun, class R, class... ArgT>
    struct delegate_impl : delegate_i<R>
    {
    	template<class F, class... ArgU>
    	delegate_impl(F&& f, ArgU&&... arg)
    		: func(std::forward<F>(f))
    		, param(std::forward<ArgU>(arg)...)
    	{}
     
    	std::unique_ptr<delegate_i<R>> clone() const
    	{ return std::make_unique<delegate_impl>(*this); }
     
    	R operator()(FUN_PARAM) const
    	{ return call(std::make_index_sequence<sizeof...(ArgT)>(),FWD_PARAM); }
    	template<class... ArgU>
    	void set(ArgU&&... arg)
    	{ param=std::make_tuple(std::forward<ArgU>(arg)...); }
     
    private:
    	template<std::size_t... I, class... ArgU>
    	R call(std::index_sequence<I...>, ArgU&&... arg) const
    	{
    		return func(
    			std::get<I>(param)
    			.get(std::forward<ArgU>(arg)...)...
    		);
    	}
     
    	typename mpl::apply<
    		PFun,R(ArgT&...)
    	>::type func;
    	std::tuple<ref_val<ArgT>...> param;
    };
     
    //(Utilisateur) Classe métier du système
    template<
    	class R,
    	class PFun =function_dyn<_>,
    	class PConv =mpl::if_<
    		std::is_same<std::decay<_>,const char*>,
    		std::string,_
    	>
    >
    struct delegate {
    	template<class F, class... Arg>
    	delegate(F&& f, Arg&&... arg) :
    		data(std::make_unique<delegate_impl<
    				PFun,R,
    				typename mpl::apply<to_store<PConv>,Arg>::type...
    			>>
    			(std::forward<F>(f),std::forward<Arg>(arg)...)
    		)
    	{}
    	delegate(const delegate& rhs)
    		: data(rhs.data->clone())
    	{}
    	delegate(delegate& rhs)
    		: data(rhs.data->clone())
    	{}
    	delegate(delegate&& rhs) =default;
     
    	delegate& operator=(const delegate& rhs)
    	{ return operator=(delegate(rhs)); }
    	delegate& operator=(delegate&&) =default;
     
    	template<class... Arg>
    	R operator()(Arg&&... arg) const
    	{ return (*data)(&arg...); }
    	template<class... Arg>
    	void set(Arg&&... arg)
    	{
    		using DynamicType = delegate_impl<
    			PFun,R,
    			typename mpl::apply<to_store<PConv>,Arg>::type...
    		>*;
     
    		if(dynamic_cast<DynamicType>(data.get()))
    			dynamic_cast<DynamicType>(data.get())->set(std::forward<Arg>(arg)...);
    	}
     
    private:
    	std::unique_ptr<delegate_i<R>> data;
    };
     
    }
     
    #include<iostream>
    #include<string>
     
    void foo(int i, int j)
    { std::cout << i << j; }
     
    int main(){
    	odfaeg::delegate<void> func(foo,odfaeg::ph<0,int>(),odfaeg::ph<1,int>());
    	func(1,2);
    	std::cout << std::endl;
    }
    Gère autant de placeholder que tu veux, il suffit juste d'adapter les deux macro. Actuellement il gère quatre placeholders.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Changer le type de la classe /erreur de compilation
    Par xamarin dans le forum Général Java
    Réponses: 11
    Dernier message: 05/05/2014, 00h01
  2. comment changer le type d'une relation ?
    Par mitapi dans le forum Access
    Réponses: 5
    Dernier message: 21/05/2007, 11h29
  3. [Débutant] Changer le type d'une colonne
    Par david71 dans le forum MS SQL Server
    Réponses: 8
    Dernier message: 08/11/2005, 12h26
  4. Probleme Alter - Changer le type d'un champ
    Par Yphon dans le forum Bases de données
    Réponses: 3
    Dernier message: 09/09/2005, 14h58
  5. Changer el type d'une variable sql sous postgre8/admin
    Par smag dans le forum PostgreSQL
    Réponses: 2
    Dernier message: 24/08/2005, 13h31

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