Partage
  • Partager sur Facebook
  • Partager sur Twitter

Plantage, copie du pointeur this.

    2 juin 2021 à 15:32:35

    Salut, je stocke le pointeur this, dans une classe et ensuite je le copie.

    Comme ceci :

    struct Test {
        Test() {
            fd = FastDelegate<void> (&Test::f, this);
            fd();
        }
        void f () {
            std::cout<<"calling function f"<<std::endl;
        }
        FastDelegate<void> fd;
    };
    
    int main(int argc, char* argv[]) {
        Test test;
    }

    Et dans la classe FastDelegate je le copie :

    namespace odfaeg {
        namespace core {
            template <size_t I, typename T>
            struct placeholder {
                using type = T;
                static constexpr std::size_t index = I;
            };
            template<class T, class U>
            struct ArgType
            {
              using type = T;
            };
    
            template<class T, class U>
            struct ArgType<T, std::reference_wrapper<U>>
            {
              using type = U&;
            };
    
            template<class T, std::size_t I, class U>
            struct ArgType<T, placeholder<I, U>>
            {
              using type = placeholder<I, U>;
            };
    
            template<class T>
            using ArgType_t = typename ArgType<T, std::remove_cv_t<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 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<size_t I, class T>
            struct ToStoreImpl<placeholder<I,T>>
            { 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;
    
            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
                {
                    std::cout<<"class : "<<typeid(C).name()<<std::endl<<"object derived : "<<typeid(*o).name()<<std::endl<<"address : "<<o<<std::endl;
                    if (o != nullptr) {
                        if(dynamic_cast<C*>(o))
                            return (dynamic_cast<C*>(o)->*pfunc)(std::forward<ArgU>(arg)...);
                        throw std::runtime_error("Invalid cast : types are nor polymorphic!");
                    }
                }
            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();
            };
            template<class F, class... ArgT>
            struct DelegateStorage {
                /** \fn FastDelegateImpl(F&& f, ArgU&&... arg)
                *   \brief constructor : create the delegate with the functor and the arguments value passed.
                */
    
                F func;
                using TupleArgs = std::tuple<ArgT...>;
                TupleArgs params;
            };
            template<std::size_t i, class T>
            struct Parameter
            {
              T value;
            };
            template<class... Placeholders>
            struct LateParameters : Parameter<Placeholders::index, typename Placeholders::type>... {
                static void deleter(void * self)
                {
                    delete static_cast<LateParameters*>(self);
                }
            };
            template<class T, class Params>
            T&& get_arg(T&& x, Params& params)
            {
                std::cout<<"arg : "<<typeid(x).name()<<std::endl<<"arddress : "<<&x<<std::endl;
                return static_cast<T&&>(x);
            }
            template <size_t I, class T, class Params>
            T& get_arg(placeholder<I, T>&, Params& params) {
                return static_cast<Parameter<I, T>&>(params).value;
            }
    
            template<class T>
            struct is_placeholder
            : std::false_type
            {};
    
            template<std::size_t I, class T>
            struct is_placeholder<placeholder<I, T>>
            : std::true_type
            {};
            struct LessPlaceceholder
            {
              template<class PlaceHolder1, class PlaceHolder2>
              using f = std::bool_constant<PlaceHolder1::index < PlaceHolder2::index>;
            };
            template<class R>
            struct FastDelegate {
                FastDelegate() = default;
                template <typename F, typename... Args>
                FastDelegate(F&& f, Args&&... args)
                : data([&]{
                namespace mp = jln::mp;
    
                using late_params_t
                  = mp::copy_if<mp::lift<is_placeholder>,
                                mp::unique<mp::sort<LessPlaceceholder,
                                                    mp::lift<LateParameters>>>>
                    ::f<std::remove_cv_t<Args>...>;
                using storage_t = DelegateStorage<DynamicFunction<R(ToStore_t<Args>&...)>, ArgType_t<Args>...>;
                auto delegate = [](Data& data) mutable {
                  auto& storage = *static_cast<storage_t*>(data.storage);
                  auto& params = *static_cast<late_params_t*>(data.params);
    
                  return std::apply([&](auto&... xs){
                    return storage.func(get_arg(xs, params)...);
                  }, storage.params);
                };
    
                auto storage_deleter = [](void * storage){
                    delete static_cast<storage_t*>(storage);
                };
                DynamicFunction<R(ToStore_t<Args>&...)> df(f);
                return Data {
                  delegate,
                  storage_deleter,
                  &late_params_t::deleter,
                  new storage_t{
                    static_cast<DynamicFunction<R(ToStore_t<Args>&...)>&&>(df),
                    typename storage_t::TupleArgs{static_cast<Args&&>(args)...}
                  },
                  nullptr,
                  sizeof(storage_t),
                  0
                };
              }())
              {}
              FastDelegate(FastDelegate& rhs)
               : data([&]{
                void* tab1 = new char[rhs.data.storage_size];
                memcpy(tab1, rhs.data.storage, rhs.data.storage_size);
                void* tab2 = nullptr;
                if (rhs.data.params != nullptr) {
                    tab2 = new char[rhs.data.params_size];
                    memcpy(tab2, rhs.data.params, rhs.data.params_size);
                }
                //std::cout<<"tab 1 : "<<tab1<<std::endl<<"rhs data.storage : "<<rhs.data.storage<<std::endl;
                return Data {
                  rhs.data.delegate,
                  rhs.data.storage_deleter,
                  rhs.data.params_deleter,
                  tab1,
                  tab2,
                  rhs.data.storage_size,
                  rhs.data.params_size
                };
              }())
              {
                //std::cout<<"data.storage : "<<sizeof(data.storage)<<std::endl<<"rhs data.storage : "<<sizeof(rhs.data.storage)<<std::endl;
    
              }
                /**\fn FastDelegate (const FastDelegate& rhs)
                *  \brief copy constructor.
                *  \param const FastDelegate& rhs : the delegate to copy.
                */
                FastDelegate(const FastDelegate& rhs)
                 : data([&]{
                    void* tab1 = new char[rhs.data.storage_size];
                    memcpy(tab1, rhs.data.storage, rhs.data.storage_size);
                    void* tab2 = nullptr;
                    if (rhs.data.params != nullptr) {
                        tab2 = new char[rhs.data.params_size];
                        memcpy(tab2, rhs.data.params, rhs.data.params_size);
                    }
                    return Data {
                      rhs.data.delegate,
                      rhs.data.storage_deleter,
                      rhs.data.params_deleter,
                      tab1,
                      tab2,
                      rhs.data.storage_size,
                      rhs.data.params_size
                    };
                  }())
                {
                    //std::cout<<"copied from const!"<<data.storage<<std::endl<<rhs.data.storage<<std::endl;
                }
                /**\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)
                {
                    void* tab1 = new char[rhs.data.storage_size];
                    memcpy(tab1, rhs.data.storage, rhs.data.storage_size);
                    void* tab2 = nullptr;
                    if (rhs.data.params != nullptr) {
                        tab2 = new char[rhs.data.params_size];
                        memcpy(tab2, rhs.data.params, rhs.data.params_size);
                    }
                    data.delegate = rhs.data.delegate;
                    data.storage_deleter = rhs.data.storage_deleter;
                    data.params_deleter = rhs.data.params_deleter;
                    /*data.storage_deleter(data.storage);
                    data.params_deleter(data.params);*/
                    data.storage = tab1;
                    data.params = tab2;
                    data.storage_size = rhs.data.storage_size;
                    data.params_size = rhs.data.params_size;
                    //std::cout<<"operator = !"<<std::endl;
                    return *this;
                }
                /**\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;
              template<typename... Args>
              bind(Args&&... args) {
                  bind_impl(std::index_sequence_for<Args...>(), static_cast<Args&&>(args)...);
              }
              template<typename... Args>
              setParams(Args&&... args) {
                using storage_t = DelegateStorage<DynamicFunction<R(ToStore_t<Args>&...)>, ArgType_t<Args>...>;
                auto& storage = *static_cast<storage_t*>(data.storage);
                data.storage = new storage_t{static_cast<DynamicFunction<R(ToStore_t<Args>&...)>&&>(storage.func), typename storage_t::TupleArgs{static_cast<Args&&>(args)...}};
              }
              R operator()() {
                  return data.delegate(data);
              }
              ~FastDelegate()
              {
                data.params_deleter(data.params);
                data.storage_deleter(data.storage);
    
              }
              private :
              template<std::size_t... Ints, class... Args>
              void bind_impl(std::index_sequence<Ints...>, Args&&... args)
              {
                  assert(!data.params);
                  using params_t = LateParameters<placeholder<Ints, ArgType_t<Args>>...>;
                  if (&params_t::deleter == data.params_deleter) {
                    data.params = new params_t{static_cast<Args&&>(args)...};
                    data.params_size = sizeof(params_t);
                  }
                  else {
                    throw std::runtime_error("bad parameter(s)");
                  }
              }
              struct Data
              {
                  R (*delegate)(Data&);
                  void (*storage_deleter)(void*);
                  void (*params_deleter)(void*);
                  void * storage;
                  void * params;
                  size_t storage_size;
                  size_t params_size;
              };
              Data data;
            };
        }
    }

    Mais ça plante!

    #0 0xfeeefeee	?? () (??:??)
    #1 0x67b00e	std::function<void (Test*&)>::operator()(Test*&) const(this=0x4bcca20, __args#0=@0x4bcca30: 0xfeeefeee) (C:/TDM-GCC-32/lib/gcc/mingw32/9.2.0/include/c++/bits/std_function.h:690)
    #2 0x747b18	_ZZZZN6odfaeg4core12FastDelegateIvEC4IM4TestFvvEJPS4_EEEOT_DpOT0_ENKUlvE_clEvENUlRNS2_4DataEE_clESF_ENKUlDpRT_E_clIJS7_EEEDaSJ_(this=0x4a7fdf0, xs#0=@0x4bcca30: 0xfeeefeee) (C:/Program Files (x86)/ODFAEG/include/odfaeg/Core/fastDelegate.h:247)
    #3 0x72f941	_ZSt13__invoke_implIvZZZN6odfaeg4core12FastDelegateIvEC4IM4TestFvvEJPS5_EEEOT_DpOT0_ENKUlvE_clEvENUlRNS3_4DataEE_clESG_EUlDpRT_E_JRS8_EES9_St14__invoke_otherOT0_DpOT1_(__f=..., __args#0=@0x4bcca30: 0xfeeefeee) (C:/TDM-GCC-32/lib/gcc/mingw32/9.2.0/include/c++/bits/invoke.h:60)
    #4 0x73bfb3	_ZSt8__invokeIZZZN6odfaeg4core12FastDelegateIvEC4IM4TestFvvEJPS5_EEEOT_DpOT0_ENKUlvE_clEvENUlRNS3_4DataEE_clESG_EUlDpRT_E_JRS8_EENSt15__invoke_resultIS9_JDpSB_EE4typeESA_SD_(__fn=..., __args#0=@0x4bcca30: 0xfeeefeee) (C:/TDM-GCC-32/lib/gcc/mingw32/9.2.0/include/c++/bits/invoke.h:95)
    #5 0x72bdb3	_ZSt12__apply_implIZZZN6odfaeg4core12FastDelegateIvEC4IM4TestFvvEJPS5_EEEOT_DpOT0_ENKUlvE_clEvENUlRNS3_4DataEE_clESG_EUlDpRT_E_RSt5tupleIJS8_EEJLj0EEEDcSA_OT0_St16integer_sequenceIjJXspT1_EEE(__f=..., __t=...) (C:/TDM-GCC-32/lib/gcc/mingw32/9.2.0/include/c++/tuple:1684)
    #6 0x73931b	_ZSt5applyIZZZN6odfaeg4core12FastDelegateIvEC4IM4TestFvvEJPS5_EEEOT_DpOT0_ENKUlvE_clEvENUlRNS3_4DataEE_clESG_EUlDpRT_E_RSt5tupleIJS8_EEEDcSA_OT0_(__f=..., __t=...) (C:/TDM-GCC-32/lib/gcc/mingw32/9.2.0/include/c++/tuple:1694)
    #7 0x746ae0	odfaeg::core::FastDelegate<void>::FastDelegate<void (Test::*)() (C:/Program Files (x86)/ODFAEG/include/odfaeg/Core/fastDelegate.h:246)
    #8 0x746a9e	odfaeg::core::FastDelegate<void>::FastDelegate<void (Test::*)() (C:/Program Files (x86)/ODFAEG/include/odfaeg/Core/fastDelegate.h:242)
    #9 0x60eee6	odfaeg::core::FastDelegate<void>::operator() (this=0x4a7ff04) (C:/Program Files (x86)/ODFAEG/include/odfaeg/Core/fastDelegate.h:367)
    #10 0x609f58	Test::Test(this=0x4a7ff04) (C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp:11)
    #11 0x4a78c9	main(argc=1, argv=0x4bc1120) (C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp:20)
    

    La copie fonctionne pour tout les types, sauf pour le pointeur this! (Et je ne sais pas pourquoi)

    Et le problème est dans la redéfinition de l'opérateur= avec le constructeur de copie ça passe.



    -
    Edité par OmbreNoire 2 juin 2021 à 16:28:34

    • Partager sur Facebook
    • Partager sur Twitter
      2 juin 2021 à 18:17:24

      Salut,

      Tu n'avais répondu à aucune de mes questions dans le topic précédent. 

      Mais vraiment je pense qu'il faudrait que tu repenses ton projet, je pense que tu es allé dans la complexité inutile. 

      Pire, si tu arrives à faire marcher un truc, ça finira probablement par planter un moment ou un autre, et pire, ce sera impossible à maintenir. 

      • Partager sur Facebook
      • Partager sur Twitter

      Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

        2 juin 2021 à 21:13:51

        Oui ce code est complexe néanmoins je ne vois pas ce qu'il y a de différent entre le pointeur this et un autre pointeur à part le fait que le pointeur this pointe sur l'objet courant, j'ai l'impression que le pointeur this change d'adresse et quand ça arrive ça plante car ce n'est plus le bon objet mais pourtant avec mon ancienne implémentation, cela fonctionne et avec le constructeur de copie également à mon avis c'est parce que je fais un return *this; que ça plante..., je vais essayer de changer cela mais si je ne sais pas pourquoi ça plante je vais devoir revenir à l'ancienne implémentation mais mon but c'est de comprendre mieux ce language est de persévérer parce que pour l'instant j'ai du mal avec les notions plus avancées et j'ai du mal à implémenter une solution moi même même si je comprends quand on me donne la solution.

        Quand on arrive à la méta programmation, les lambdas expressions et les void* précisément je galère. Il m'arrive souvent de manipuler du code que je ne comprends pas. Cet solution utilisé les trois points que j'ai le plus de mal à comprendre. 

        mp::copy, sort et tout ça je ne sais pas comment ça marche. 

        Et au niveau de la correspondance des types des paramètres template j'ai du mal aussi avec les classes de traits, bref, j'avais lu des tutoriels mais c'est tellement loin et le fichier mp.h est trop volumineux pour comprendre surtout pour un débutant je pense qu'il y a moyen de faire ça plus simplement mais je ne vois pas comment je serai incapable d'implémenter ça moi même.

        Sur développer.com avec mon ancienne implémentation j'ai eu des explications et quand ça ne fonctionnait pas on m'expliquait mais ici, ce n'est pas la même chose quand quelqu'un me propose une solution et que ça plante pas de solution comme si la personne ne comprenais pas le code qu'elle me donne et parfois la solution est tellement bête que je la trouve moi même.., mais pas de réponses à part des critiques. 

        Alors on voit tout de suite les personnes expertes comme celui qui m'a montré l'ancienne implémentation et les personnes novices qui donne un code sans le comprendre ou quand je poste un code on ne le comprend pas.

        EDIT : Il faut avouer que la syntaxe du c++ moderne n'est pas évidente je crois pas qu'on sache voir le code généré par les template comme avec le préprocesseur.  

        -
        Edité par OmbreNoire 2 juin 2021 à 21:22:29

        • Partager sur Facebook
        • Partager sur Twitter
          2 juin 2021 à 21:37:14

          Pourquoi ne pas utiliser le débogueur pour voir où ça pêche avec cette usine à gaz ?

          Déjà que le simple fait que "this" d'un même objet qui utilise de l'héritage multiple n'est pas constant, alors le stocker ailleurs, même pas en rêve.

          • Partager sur Facebook
          • Partager sur Twitter
          Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
            2 juin 2021 à 22:58:17

            Oui, mais je redemande, pourquoi as tu besoin de faire cela ?

            Est ce que c'est un exercice ? Tu cherches à faire le truc le plus fou possible ? 

            Ce n'est pas parce que le C++ moderne propose plein d'outils qu'il faut les utiliser n'importe quand de n'importe quelle façon !

            Déjà, normalement un gars qui programme avec des lambda, des template et des classes de traits comme tu dis, c'est un "moderne", et il a abandonné les pointeurs, et surtout les void* ! 

            Mêler les deux, c'est mêler deux mondes qui ne devraient pas cohabiter.

            Ou alors on se la fait en C, void* et taille, et basta, memcpy et c'est plié, ça me va aussi !

            Etre bon en C++, ce n'est pas faire les choses les plus compliquées possibles.

            Il faut penser à maintenir le code ! 

            Je suis dans le monde professionnel depuis 17 ans, et le mec qui me fait ça au boulot, c'est la peine de mort... minimum !

            Si on bricole, et que tu me dis :

            "regarde, cette pointe je la mets dans le mur, je mets 3 équerres, un gyroscope, des tasseaux, je fais une entaille à la scie électrique, je sors une perceuse à visée laser, je...."

            - tu veux faire quoi ?

            - mettre un cadre ! bien droit !

            - ben moi je prends un niveau à bulle, 2 clous et c'est plié...

            Essaie de nous définir une fois pour toutes quelle est ton besoin. Concrètement. Et va droit au but !

            • Partager sur Facebook
            • Partager sur Twitter

            Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

              2 juin 2021 à 23:18:21

              Ok, le problème est bien celui auquel je pense : l'adresse du pointeur this n'est pas la même dans la classe Test et dans la classe FastDelegate, elle change!

              La question que je me pose maintenant c'est pourquoi ?

              La valeur du pointeur this est 0x4a3ff4 mais dans la classe FastDelegate elle prend une valeur bizarre qui est 0xfeefee

              Et le pire c'est que ça ne me le fait pas tout le temps. (comportement indéterminé)

              Il appelle le constructeur ici et pas l'opérateur= ni le constructeur de copie je me demande si c'est normal.

              Bref, je ne comprend pas pourquoi ça plante donc je ne saurai pas résoudre ce problème.

              template<class R>
                      struct FastDelegate {
                          FastDelegate() = default;
                          template <typename F, typename... Args>
                          FastDelegate(F&& f, Args&&... args)
                          : data([&]{
                          namespace mp = jln::mp;
              
                          using late_params_t
                            = mp::copy_if<mp::lift<is_placeholder>,
                                          mp::unique<mp::sort<LessPlaceceholder,
                                                              mp::lift<LateParameters>>>>
                              ::f<std::remove_cv_t<Args>...>;
                          using storage_t = DelegateStorage<DynamicFunction<R(ToStore_t<Args>&...)>, ArgType_t<Args>...>;
                          auto delegate = [](Data& data) mutable {
                            auto& storage = *static_cast<storage_t*>(data.storage);
                            auto& params = *static_cast<late_params_t*>(data.params);
              
                            return std::apply([&](auto&... xs){
                              return storage.func(get_arg(xs, params)...);
                            }, storage.params);
                          };
              
                          auto storage_deleter = [](void * storage){
                              delete static_cast<storage_t*>(storage);
                          };
                          DynamicFunction<R(ToStore_t<Args>&...)> df(f);
                          return Data {
                            delegate,
                            storage_deleter,
                            &late_params_t::deleter,
                            new storage_t{
                              static_cast<DynamicFunction<R(ToStore_t<Args>&...)>&&>(df),
                              typename storage_t::TupleArgs{static_cast<Args&&>(args)...}
                            },
                            nullptr,
                            sizeof(storage_t),
                            0
                          };
                        }())
                        {
                            std::cout<<"constructor"<<std::endl;
                        }
                        FastDelegate(FastDelegate& rhs)
                         : data([&]{
                          void* tab1 = new char[rhs.data.storage_size];
                          memcpy(tab1, rhs.data.storage, rhs.data.storage_size);
                          void* tab2 = nullptr;
                          if (rhs.data.params != nullptr) {
                              tab2 = new char[rhs.data.params_size];
                              memcpy(tab2, rhs.data.params, rhs.data.params_size);
                          }
              
                          return Data {
                            rhs.data.delegate,
                            rhs.data.storage_deleter,
                            rhs.data.params_deleter,
                            tab1,
                            tab2,
                            rhs.data.storage_size,
                            rhs.data.params_size
                          };
                        }())
                        {
                          std::cout<<"copy constructor"<<std::endl;
              
                        }
                          /**\fn FastDelegate (const FastDelegate& rhs)
                          *  \brief copy constructor.
                          *  \param const FastDelegate& rhs : the delegate to copy.
                          */
                          FastDelegate(const FastDelegate& rhs)
                           : data([&]{
                              void* tab1 = new char[rhs.data.storage_size];
                              memcpy(tab1, rhs.data.storage, rhs.data.storage_size);
                              void* tab2 = nullptr;
                              if (rhs.data.params != nullptr) {
                                  tab2 = new char[rhs.data.params_size];
                                  memcpy(tab2, rhs.data.params, rhs.data.params_size);
                              }
              
                              return Data {
                                rhs.data.delegate,
                                rhs.data.storage_deleter,
                                rhs.data.params_deleter,
                                tab1,
                                tab2,
                                rhs.data.storage_size,
                                rhs.data.params_size
                              };
                            }())
                          {
                              std::cout<<"copy constructor (const)"<<std::endl;
                          }
                          /**\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)
                          {
                              /*void* tab1 = new char[rhs.data.storage_size];
                              memcpy(tab1, rhs.data.storage, rhs.data.storage_size);
                              void* tab2 = nullptr;
                              if (rhs.data.params != nullptr) {
                                  tab2 = new char[rhs.data.params_size];
                                  memcpy(tab2, rhs.data.params, rhs.data.params_size);
                              }
                              data.delegate = rhs.data.delegate;
                              data.storage_deleter = rhs.data.storage_deleter;
                              data.params_deleter = rhs.data.params_deleter;
                              data.storage = tab1;
                              data.params = tab2;
                              data.storage_size = rhs.data.storage_size;
                              data.params_size = rhs.data.params_size;
                              //std::cout<<"operator = !"<<std::endl;
                              return *this;*/
                              std::cout<<"operation affector"<<std::endl;
                              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;
                        template<typename... Args>
                        bind(Args&&... args) {
                            bind_impl(std::index_sequence_for<Args...>(), static_cast<Args&&>(args)...);
                        }
                        template<typename... Args>
                        setParams(Args&&... args) {
                          using storage_t = DelegateStorage<DynamicFunction<R(ToStore_t<Args>&...)>, ArgType_t<Args>...>;
                          auto& storage = *static_cast<storage_t*>(data.storage);
                          data.storage = new storage_t{static_cast<DynamicFunction<R(ToStore_t<Args>&...)>&&>(storage.func), typename storage_t::TupleArgs{static_cast<Args&&>(args)...}};
                        }
                        template<typename... Args>
                        R operator()(Args&&... args) {
                            using storage_t = DelegateStorage<DynamicFunction<R(ToStore_t<Args>&...)>, ArgType_t<Args>...>;
                            auto& storage = *static_cast<storage_t*>(data.storage);
              
                            display_params(std::index_sequence_for<Args...>(), storage.params);
                            return data.delegate(data);
                        }
                        ~FastDelegate()
                        {
                          data.params_deleter(data.params);
                          data.storage_deleter(data.storage);
              
                        }
                        private :
                        template<std::size_t... Ints, class... Args>
                        void display_params(std::index_sequence<Ints...>, std::tuple<Args...> args) {
                            printf("%s%x%s", "value of this in delegate : ",  std::get<Ints>(args)..., "\n");
                        }
                        template<std::size_t... Ints, class... Args>
                        void bind_impl(std::index_sequence<Ints...>, Args&&... args)
                        {
                            assert(!data.params);
                            using params_t = LateParameters<placeholder<Ints, ArgType_t<Args>>...>;
                            if (&params_t::deleter == data.params_deleter) {
                              data.params = new params_t{static_cast<Args&&>(args)...};
                              data.params_size = sizeof(params_t);
                            }
                            else {
                              throw std::runtime_error("bad parameter(s)");
                            }
                        }
                        struct Data
                        {
                            R (*delegate)(Data&);
                            void (*storage_deleter)(void*);
                            void (*params_deleter)(void*);
                            void * storage;
                            void * params;
                            size_t storage_size;
                            size_t params_size;
                        };
                        Data data;
                      };
              struct Test {
                  Test() {
                      std::cout<<"this pointer value in class Test : "<<this<<std::endl;
                      fd = FastDelegate<void> (&Test::f, this);
                      fd(this);
              
                  }
                  void f () {
                      std::cout<<"calling function f"<<std::endl;
                  }
                  FastDelegate<void> fd;
              };
              
              int main(int argc, char* argv[]) {
                  Test test;
                  return 0;
              }




              Avec l'ancienne implémentation je n'ai pas ce problème mais je la stocke dans une structure Val et puis RefVal avant de la passer au tuple, ce que jo_link ne fait pas parce que qu'il m'a dit qu'il n'y a pas besoin d'héritage pour faire ça!!!

              Enfin bref, voilà une image qui illustre le problème : (peut être c'est parce que jo_link la stocke dans un tuple et que le tuple prend une référence ?)

              Si oui, comment copier les éléments dans le tuple plutôt que de les référencer ?

              -
              Edité par OmbreNoire 2 juin 2021 à 23:25:27

              • Partager sur Facebook
              • Partager sur Twitter
                3 juin 2021 à 1:03:36

                >0xfeefee

                0xfeefee ou 0xfeeefeee ???

                https://www.nobugs.org/developer/win32/debug_crt_heap.html

                Vous avez donc vraisemblablement pris un objet qui c'est fait "libéré" en DEBUG, avant que la mémoire ne se fasse recyclée.

                >Et le pire c'est que ça ne me le fait pas tout le temps. (comportement indéterminé)

                Chez ceux que tu n'écoutes pas, on appelle ça une UB (https://en.cppreference.com/w/cpp/language/ub ), c'est pas faute de t'avoir prévenu de ne pas faire n'importe quoi, juste parce que ça à l'air de fonctionner, les nuits de pleine lune, dans un pentacle fait de sang de poulet fraîchement égorgé, par une brise du Sud-Sud/Est.

                >Il appelle le constructeur ici

                C'est quelle ligne le "ici" ???

                >Bref, je ne comprend pas pourquoi ça plante

                Bin, utilisez le débogueur pour qu'il vous informe quand la valeur change vers une valeur incorrecte, c'est tout.

                • Partager sur Facebook
                • Partager sur Twitter
                Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                  3 juin 2021 à 1:12:39

                  bacelar a écrit:

                  >0xfeefee

                  0xfeefee ou 0xfeeefeee ???

                  https://www.nobugs.org/developer/win32/debug_crt_heap.html

                  Vous avez donc vraisemblablement pris un objet qui c'est fait "libéré" en DEBUG, avant que la mémoire ne se fasse recyclée.

                  >Et le pire c'est que ça ne me le fait pas tout le temps. (comportement indéterminé)

                  Chez ceux que tu n'écoutes pas, on appelle ça une UB (https://en.cppreference.com/w/cpp/language/ub ), c'est pas faute de t'avoir prévenu de ne pas faire n'importe quoi, juste parce que ça à l'air de fonctionner, les nuits de pleine lune, dans un pentacle fait de sang de poulet fraîchement égorgé, par une brise du Sud-Sud/Est.

                  >Il appelle le constructeur ici

                  C'est quelle ligne le "ici" ???

                  >Bref, je ne comprend pas pourquoi ça plante

                  Bin, utilisez le débogueur pour qu'il vous informe quand la valeur change vers une valeur incorrecte, c'est tout.

                  0xfeefee ou 0xfeeefeee ???

                  Oui il faudrait que je regarde quand la valeur change et prend une valeur incorrecte, ça me le fait aussi en release car ça plante aussi en release dans certains cas de figure.

                  • Partager sur Facebook
                  • Partager sur Twitter
                    3 juin 2021 à 7:24:23

                    Et c'est grave que ça plante ?
                    • Partager sur Facebook
                    • Partager sur Twitter
                      3 juin 2021 à 10:26:25

                      Il appelle le destructeur de la classe FastDelegate<void> après avoir appelé le constructeur.

                      template<class R>
                              struct FastDelegate {
                                  FastDelegate() :
                                  data([&]{
                                       return Data {
                                           nullptr,
                                           nullptr,
                                           nullptr,
                                           nullptr,
                                           nullptr,
                                           0,
                                           0
                                       };
                                  }())
                                  {
                      
                                  }
                                  template <typename F, typename... Args>
                                  FastDelegate(F&& f, Args&&... args)
                                  : data([&]{
                                  namespace mp = jln::mp;
                      
                                  using late_params_t
                                    = mp::copy_if<mp::lift<is_placeholder>,
                                                  mp::unique<mp::sort<LessPlaceceholder,
                                                                      mp::lift<LateParameters>>>>
                                      ::f<std::remove_cv_t<Args>...>;
                                  using storage_t = DelegateStorage<DynamicFunction<R(ToStore_t<Args>&...)>, ArgType_t<Args>...>;
                                  auto delegate = [](Data& data) mutable {
                                    auto& storage = *static_cast<storage_t*>(data.storage);
                                    auto& params = *static_cast<late_params_t*>(data.params);
                                    printf("%s%x%s", "value of this in delegate (delegate) : ",  std::get<Args>(storage.params)..., "\n");
                                    return std::apply([&](auto&... xs){
                                      printf("%s%x%s", "value of this in delegate (std::apply) : ",  std::get<Args>(storage.params)..., "\n");
                                      return storage.func(get_arg(xs, params)...);
                                    }, storage.params);
                                  };
                      
                                  auto storage_deleter = [](void * storage){
                                      std::cout<<"delete storage"<<std::endl;
                                      delete static_cast<storage_t*>(storage);
                                  };
                                  DynamicFunction<R(ToStore_t<Args>&...)> df(f);
                                  return Data {
                                    delegate,
                                    storage_deleter,
                                    &late_params_t::deleter,
                                    new storage_t{
                                      static_cast<DynamicFunction<R(ToStore_t<Args>&...)>&&>(df),
                                      typename storage_t::TupleArgs{static_cast<Args&&>(args)...}
                                    },
                                    nullptr,
                                    sizeof(storage_t),
                                    0
                                  };
                                }())
                                {
                                    std::cout<<"constructor"<<std::endl;
                                }
                                FastDelegate(FastDelegate& rhs)
                                 : data([&]{
                                  void* tab1 = new char[rhs.data.storage_size];
                                  memcpy(tab1, rhs.data.storage, rhs.data.storage_size);
                                  void* tab2 = nullptr;
                                  if (rhs.data.params != nullptr) {
                                      tab2 = new char[rhs.data.params_size];
                                      memcpy(tab2, rhs.data.params, rhs.data.params_size);
                                  }
                      
                                  return Data {
                                    rhs.data.delegate,
                                    rhs.data.storage_deleter,
                                    rhs.data.params_deleter,
                                    tab1,
                                    tab2,
                                    rhs.data.storage_size,
                                    rhs.data.params_size
                                  };
                                }())
                                {
                                  std::cout<<"copy constructor"<<std::endl;
                      
                                }
                                  /**\fn FastDelegate (const FastDelegate& rhs)
                                  *  \brief copy constructor.
                                  *  \param const FastDelegate& rhs : the delegate to copy.
                                  */
                                  FastDelegate(const FastDelegate& rhs)
                                   : data([&]{
                                      void* tab1 = new char[rhs.data.storage_size];
                                      memcpy(tab1, rhs.data.storage, rhs.data.storage_size);
                                      void* tab2 = nullptr;
                                      if (rhs.data.params != nullptr) {
                                          tab2 = new char[rhs.data.params_size];
                                          memcpy(tab2, rhs.data.params, rhs.data.params_size);
                                      }
                      
                                      return Data {
                                        rhs.data.delegate,
                                        rhs.data.storage_deleter,
                                        rhs.data.params_deleter,
                                        tab1,
                                        tab2,
                                        rhs.data.storage_size,
                                        rhs.data.params_size
                                      };
                                    }())
                                  {
                                      std::cout<<"copy constructor"<<std::endl;
                                  }
                                  /**\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)
                                  {
                                      /*void* tab1 = new char[rhs.data.storage_size];
                                      memcpy(tab1, rhs.data.storage, rhs.data.storage_size);
                                      void* tab2 = nullptr;
                                      if (rhs.data.params != nullptr) {
                                          tab2 = new char[rhs.data.params_size];
                                          memcpy(tab2, rhs.data.params, rhs.data.params_size);
                                      }
                                      data.delegate = rhs.data.delegate;
                                      data.storage_deleter = rhs.data.storage_deleter;
                                      data.params_deleter = rhs.data.params_deleter;
                                      data.storage = tab1;
                                      data.params = tab2;
                                      data.storage_size = rhs.data.storage_size;
                                      data.params_size = rhs.data.params_size;
                                      //std::cout<<"operator = !"<<std::endl;
                                      return *this;*/
                                      std::cout<<"operation affector"<<std::endl;
                                      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;
                                template<typename... Args>
                                bind(Args&&... args) {
                                    bind_impl(std::index_sequence_for<Args...>(), static_cast<Args&&>(args)...);
                                }
                                template<typename... Args>
                                setParams(Args&&... args) {
                                  using storage_t = DelegateStorage<DynamicFunction<R(ToStore_t<Args>&...)>, ArgType_t<Args>...>;
                                  auto& storage = *static_cast<storage_t*>(data.storage);
                                  data.storage = new storage_t{static_cast<DynamicFunction<R(ToStore_t<Args>&...)>&&>(storage.func), typename storage_t::TupleArgs{static_cast<Args&&>(args)...}};
                                }
                                template<typename... Args>
                                R operator()() {
                                    using storage_t = DelegateStorage<DynamicFunction<R(ToStore_t<Args>&...)>, ArgType_t<Args>...>;
                                    auto& storage = *static_cast<storage_t*>(data.storage);
                      
                                    //display_params(std::index_sequence_for<Args...>(), storage.params);
                                    //return data.delegate(data);
                                }
                                ~FastDelegate()
                                {
                                  if (data.params_deleter != nullptr)
                                      data.params_deleter(data.params);
                                  if (data.storage_deleter != nullptr)
                                      data.storage_deleter(data.storage);
                                }
                                private :
                                template<std::size_t... Ints, class... Args>
                                void display_params(std::index_sequence<Ints...>, std::tuple<Args...> args) {
                                    printf("%s%x%s", "value of this in delegate : ",  std::get<Ints>(args)..., "\n");
                                }
                                template<std::size_t... Ints, class... Args>
                                void bind_impl(std::index_sequence<Ints...>, Args&&... args)
                                {
                                    assert(!data.params);
                                    using params_t = LateParameters<placeholder<Ints, ArgType_t<Args>>...>;
                                    if (&params_t::deleter == data.params_deleter) {
                                      data.params = new params_t{static_cast<Args&&>(args)...};
                                      data.params_size = sizeof(params_t);
                                    }
                                    else {
                                      throw std::runtime_error("bad parameter(s)");
                                    }
                                }
                                struct Data
                                {
                                    R (*delegate)(Data&);
                                    void (*storage_deleter)(void*);
                                    void (*params_deleter)(void*);
                                    void * storage;
                                    void * params;
                                    size_t storage_size;
                                    size_t params_size;
                                };
                                Data data;
                              };
                      struct Test2 {
                          Test2() {
                              std::cout<<"value of this : "<<this<<std::endl;
                              test = FastDelegate<void>(&Test2::f, this);
                              test();
                          }
                          void f(){
                              std::cout<<"calling function f2"<<std::endl;
                          }
                          FastDelegate<void> test;
                      };
                      int main(int argc, char* argv[]) {
                          Test2 t2;
                      
                      
                          //std::cout<<"t2"<<std::endl;
                      
                          return 0;
                      }

                      Pourquoi il appelle le destructeur hors que je ne détruit pas le delegate après sa création ???

                      Lorsque je test le code dans le main ça ne me le fait pas! (C'est lorsque j'utilise le code qui est dans ma lib statique)

                      Test() :
                                  data([&]{
                                       return Data {
                                           nullptr,
                                           nullptr,
                                           nullptr,
                                           nullptr,
                                           nullptr,
                                           0,
                                           0
                                       };
                                  }())
                                  {
                      
                                  }
                          template <typename F, typename... Args>
                          Test(F&& f, Args&&... args) :
                          data([&]{
                                  namespace mp = jln::mp;
                      
                                  using late_params_t
                                    = mp::copy_if<mp::lift<is_placeholder>,
                                                  mp::unique<mp::sort<LessPlaceceholder,
                                                                      mp::lift<LateParameters>>>>
                                      ::f<std::remove_cv_t<Args>...>;
                                  using storage_t = DelegateStorage<DynamicFunction<R(ToStore_t<Args>&...)>, ArgType_t<Args>...>;
                                  auto delegate = [](Data& data) mutable {
                                    auto& storage = *static_cast<storage_t*>(data.storage);
                                    auto& params = *static_cast<late_params_t*>(data.params);
                      
                                    return std::apply([&](auto&... xs){
                                      return storage.func(get_arg(xs, params)...);
                                    }, storage.params);
                                  };
                      
                                  auto storage_deleter = [](void * storage){
                                      std::cout<<"delete storage"<<std::endl;
                                      delete static_cast<storage_t*>(storage);
                                  };
                                  DynamicFunction<R(ToStore_t<Args>&...)> df(f);
                                  return Data {
                                    delegate,
                                    storage_deleter,
                                    &late_params_t::deleter,
                                    new storage_t{
                                      static_cast<DynamicFunction<R(ToStore_t<Args>&...)>&&>(df),
                                      typename storage_t::TupleArgs{static_cast<Args&&>(args)...}
                                    },
                                    nullptr,
                                    sizeof(storage_t),
                                    0
                                  };
                              }())
                          {
                      
                          }
                          Test(Test& rhs)
                                 : data([&]{
                                  void* tab1 = new char[rhs.data.storage_size];
                                  memcpy(tab1, rhs.data.storage, rhs.data.storage_size);
                                  void* tab2 = nullptr;
                                  if (rhs.data.params != nullptr) {
                                      tab2 = new char[rhs.data.params_size];
                                      memcpy(tab2, rhs.data.params, rhs.data.params_size);
                                  }
                      
                                  return Data {
                                    rhs.data.delegate,
                                    rhs.data.storage_deleter,
                                    rhs.data.params_deleter,
                                    tab1,
                                    tab2,
                                    rhs.data.storage_size,
                                    rhs.data.params_size
                                  };
                                }())
                                {
                                  std::cout<<"copy constructor"<<std::endl;
                      
                                }
                                  /**\fn FastDelegate (const FastDelegate& rhs)
                                  *  \brief copy constructor.
                                  *  \param const FastDelegate& rhs : the delegate to copy.
                                  */
                                  Test(const Test& rhs)
                                   : data([&]{
                                      void* tab1 = new char[rhs.data.storage_size];
                                      memcpy(tab1, rhs.data.storage, rhs.data.storage_size);
                                      void* tab2 = nullptr;
                                      if (rhs.data.params != nullptr) {
                                          tab2 = new char[rhs.data.params_size];
                                          memcpy(tab2, rhs.data.params, rhs.data.params_size);
                                      }
                      
                                      return Data {
                                        rhs.data.delegate,
                                        rhs.data.storage_deleter,
                                        rhs.data.params_deleter,
                                        tab1,
                                        tab2,
                                        rhs.data.storage_size,
                                        rhs.data.params_size
                                      };
                                    }())
                                  {
                                      std::cout<<"copy constructor"<<std::endl;
                                  }
                                  /**\fn FastDelegate (FastDelegate& rhs)
                                  *  \brief move constructor.
                                  *  \param FastDelegate&& rhs : the delegate to move.
                                  */
                                  Test(Test&& 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.
                                  */
                                  Test& operator=(const Test& rhs)
                                  {
                                      /*void* tab1 = new char[rhs.data.storage_size];
                                      memcpy(tab1, rhs.data.storage, rhs.data.storage_size);
                                      void* tab2 = nullptr;
                                      if (rhs.data.params != nullptr) {
                                          tab2 = new char[rhs.data.params_size];
                                          memcpy(tab2, rhs.data.params, rhs.data.params_size);
                                      }
                                      data.delegate = rhs.data.delegate;
                                      data.storage_deleter = rhs.data.storage_deleter;
                                      data.params_deleter = rhs.data.params_deleter;
                                      data.storage = tab1;
                                      data.params = tab2;
                                      data.storage_size = rhs.data.storage_size;
                                      data.params_size = rhs.data.params_size;
                                      //std::cout<<"operator = !"<<std::endl;
                                      return *this;*/
                                      std::cout<<"operation affector"<<std::endl;
                                      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.
                                  */
                                  Test& operator=(Test&&) =default;
                          R operator()() {
                              return data.delegate(data);
                          }
                          template<typename... Args>
                            bind(Args&&... args) {
                                bind_impl(std::index_sequence_for<Args...>(), static_cast<Args&&>(args)...);
                            }
                            template<typename... Args>
                            setParams(Args&&... args) {
                              using storage_t = DelegateStorage<DynamicFunction<R(ToStore_t<Args>&...)>, ArgType_t<Args>...>;
                              auto& storage = *static_cast<storage_t*>(data.storage);
                              data.storage = new storage_t{static_cast<DynamicFunction<R(ToStore_t<Args>&...)>&&>(storage.func), typename storage_t::TupleArgs{static_cast<Args&&>(args)...}};
                            }
                          private :
                          template<std::size_t... Ints, class... Args>
                            void bind_impl(std::index_sequence<Ints...>, Args&&... args)
                            {
                                assert(!data.params);
                                using params_t = LateParameters<placeholder<Ints, ArgType_t<Args>>...>;
                                if (&params_t::deleter == data.params_deleter) {
                                  data.params = new params_t{static_cast<Args&&>(args)...};
                                  data.params_size = sizeof(params_t);
                                }
                                else {
                                  throw std::runtime_error("bad parameter(s)");
                                }
                            }
                          struct Data {
                            void (*delegate)(Data&);
                            void (*storage_deleter)(void*);
                            void (*params_deleter)(void*);
                            void * storage;
                            void * params;
                            size_t storage_size;
                            size_t params_size;
                          };
                          Data data;
                      };
                      struct Test2 {
                          Test2() {
                              std::cout<<"value of this : "<<this<<std::endl;
                              test = Test<void>(&Test2::f, this);
                              test();
                          }
                          void f(){
                              std::cout<<"calling function f2"<<std::endl;
                          }
                          Test<void> test;
                      };
                      int main(int argc, char* argv[]) {
                          Test2 t2;
                      
                      
                          //std::cout<<"t2"<<std::endl;
                      
                          return 0;
                      }

                      Pas normal tout ça il n'a pas à appeler le destructeur là si il appelle le destructeur quand il ne faut pas je comprend pourquoi j'ai des plantages.

                      Je vais essayer avec un autre compilateur.



                      • Partager sur Facebook
                      • Partager sur Twitter
                        3 juin 2021 à 10:42:53

                        Essaie surtout de réfléchir un peu :

                        #include <iostream>
                        
                        struct Coin
                        {
                            Coin(void * bidule = nullptr)
                              : bidule{ bidule }
                            {
                                std::cout << "Coin ctor " << bidule << std::endl;
                            }
                        
                            ~Coin()
                            {
                                std::cout << "Coin dtor " << bidule << std::endl;
                            }
                        
                            void operator()()
                            {
                                std::cout << "Coin operator() " << bidule << std::endl;
                            }
                        
                            void * bidule;
                        };
                        
                        struct Test
                        {
                            Test()
                            {
                                std::cout << "Test 0" << std::endl;
                                coin = Coin{this};
                                coin();
                                std::cout << "Test 1" << std::endl;
                            }
                            Coin coin;
                        };
                        int main(int argc, char* argv[])
                        {
                            Test t;
                            return 0;
                        }


                        Lance ce bout de code, et tu comprendras...

                        EDIT

                        Quand on préconise l'utilisation des listes d'init, c'est pas pour emmerder le monde

                        -
                        Edité par dragonjoker 3 juin 2021 à 10:47:01

                        • Partager sur Facebook
                        • Partager sur Twitter

                        Si vous ne trouvez plus rien, cherchez autre chose.

                          3 juin 2021 à 11:03:26

                          Je crois qu'il détruit Coin{this}; après l'avoir passé à l'opérateur=, mais le problème ne vient pas de là parce que j'ai mit le code du destructeur en commentaire et ça plante encore. (plus le code que j'ai présenté plus haut mais, celui-ci : )

                          EXPORT_CLASS_GUID(BoundingVolumeBoundingBox, BoundingVolume, BoundingBox)
                              EXPORT_CLASS_GUID(EntityTile, Entity, Tile)
                              EXPORT_CLASS_GUID(EntityBigTile, Entity, BigTile)
                              EXPORT_CLASS_GUID(EntityWall, Entity, g2d::Wall)
                              EXPORT_CLASS_GUID(EntityDecor, Entity, g2d::Decor)
                              EXPORT_CLASS_GUID(EntityAnimation, Entity, Anim)
                              EXPORT_CLASS_GUID(EntityMesh, Entity, Mesh)
                              EXPORT_CLASS_GUID(EntityParticleSystem, Entity, ParticleSystem)
                              EXPORT_CLASS_GUID(ShapeRectangleShape, Shape, RectangleShape)
                              ODFAEGCreator app(sf::VideoMode(1000,700),"ODFAEG Creator");
                              return app.exec();

                          Bref, je pense que je vais repasser à l'ancienne implémentation de ma classe FastDelegate.

                          J'ai des cas parfois ça marche, parfois ça marche pas et je sais pas trop pourquoi ça plante, déjà le type affiché à l'exécution avec typeid n'est pas le même avec la nouvelle et l'ancienne implémentation, avec la nouvelle implémentation ça m'affiche le type d'un objet qui ne possède pas la fonction membre (ODFAEGCreator*) et avec l'ancienne le bon type (MenuItem) à l'appel de l'opérateur= dans DynamicWrapper, donc déjà là le type à l'exécution n'est pas bon dans certains cas.

                          -
                          Edité par OmbreNoire 3 juin 2021 à 11:15:17

                          • Partager sur Facebook
                          • Partager sur Twitter
                            5 juin 2021 à 0:27:50

                            Bon je sais pas trop ce qui se passe avec ce compilo mais c'est bizarre ça ne m'étonne pas que ça plante :

                            template<class R>
                                    struct FastDelegate {
                                        FastDelegate() :
                                        data([&]{
                                             return Data {
                                                 nullptr,
                                                 nullptr,
                                                 nullptr,
                                                 nullptr,
                                                 nullptr,
                                                 0,
                                                 0
                                             };
                                        }())
                                        {
                                            std::cout<<"default constructor"<<std::endl;
                                        }
                                        template <typename F, typename... Args>
                                        FastDelegate(F&& f, Args&&... args)
                                        : data([&]{
                                        namespace mp = jln::mp;
                            
                                        using late_params_t
                                          = mp::copy_if<mp::lift<is_placeholder>,
                                                        mp::unique<mp::sort<LessPlaceceholder,
                                                                            mp::lift<LateParameters>>>>
                                            ::f<std::remove_cv_t<Args>...>;
                                        using storage_t = DelegateStorage<DynamicFunction<R(ToStore_t<Args>&...)>, ArgType_t<Args>...>;
                                        auto delegate = [](Data& data) mutable {
                                          auto& storage = *static_cast<storage_t*>(data.storage);
                                          auto& params = *static_cast<late_params_t*>(data.params);
                                          //printf("%s%x%s", "value of this in delegate (delegate) : ",  std::get<Args>(storage.params)..., "\n");
                                          return std::apply([&](auto&... xs){
                                            //printf("%s%x%s", "value of this in delegate (std::apply) : ",  std::get<Args>(storage.params)..., "\n");
                                            return storage.func(get_arg(xs, params)...);
                                          }, storage.params);
                                        };
                                        auto storage_deleter = [](void * storage){
                                            std::cout<<"delete storage : "<<storage<<std::endl;
                                            delete static_cast<storage_t*>(storage);
                                        };
                                        size_t size = sizeof(storage_t);
                                        std::cout<<"size in ctor: "<<size<<","<<(size / 8)<<","<<(size / 8 * 8)<<std::endl;
                                        DynamicFunction<R(ToStore_t<Args>&...)> df(f);
                                        return Data {
                                          delegate,
                                          storage_deleter,
                                          &late_params_t::deleter,
                                          new storage_t{
                                            static_cast<DynamicFunction<R(ToStore_t<Args>&...)>&&>(df),
                                            typename storage_t::TupleArgs{static_cast<Args&&>(args)...}
                                          },
                                          nullptr,
                                          (sizeof(storage_t)/8*8),
                                          0
                                        };
                                      }())
                                      {
                                          std::cout<<"constructor"<<std::endl;
                                      }

                            18/8 ça fait pas 3 (ça fait 2) et 3*8 ça fait pas 18. (ça fait 24)

                            14/8 ça fait pas 2 (ça fait 1) et 2*8 ça fait pas 18. (ça fait 16)



                            • Partager sur Facebook
                            • Partager sur Twitter
                              5 juin 2021 à 1:36:23

                              Pourquoi tu divises par 8 ? A priori, aucune raison que la taille de ta classe soit un multiple de 8.

                              Testé avec MSVC 2019. Aucune idée de pourquoi tu as ce résultat. Il faut vérifier tes paramètres de build.

                              • Partager sur Facebook
                              • Partager sur Twitter
                                5 juin 2021 à 7:07:46

                                J'utilise tdm-gcc32 bits et comme option de compilation j'ai -std=cpp17 et -g en debug sinon -O2 et -s en release.

                                Par contre il y a moulte d'erreurs sous vs :

                                Gravité	Code	Description	Projet	Fichier	Ligne	État de la suppression
                                Erreur	C1903	impossible de récupérer à partir des erreurs précédentes ; arrêt de la compilation	odfaeg-graphics	C:\Users\Laurent\Windows\ODFAEG\include\odfaeg\Core\mp.hpp	13698	Erreur	C1083	Impossible d'ouvrir le fichier include : 'dirent.h' : No such file or directory	odfaeg-core	C:\Users\Laurent\Windows\ODFAEG\include\odfaeg\Core\utilities.h	8	
                                Erreur	C2397	la conversion de 'size_t' en 'jln::mp::int_' requiert une conversion restrictive	odfaeg-core	C:\Users\Laurent\Windows\ODFAEG\include\odfaeg\Core\mp.hpp	11811	
                                Erreur	C2397	la conversion de 'size_t' en 'jln::mp::int_' requiert une conversion restrictive	odfaeg-core	C:\Users\Laurent\Windows\ODFAEG\include\odfaeg\Core\mp.hpp	11819	
                                Erreur	C2065	'typed_value' : identificateur non déclaré	odfaeg-core	C:\Users\Laurent\Windows\ODFAEG\include\odfaeg\Core\mp.hpp	13311	
                                Erreur	C2059	erreur de syntaxe : 'decltype'	odfaeg-core	C:\Users\Laurent\Windows\ODFAEG\include\odfaeg\Core\mp.hpp	13311	
                                Erreur	C2653	'x' : n'est pas un nom de classe ni d'espace de noms	odfaeg-core	C:\Users\Laurent\Windows\ODFAEG\include\odfaeg\Core\mp.hpp	13311	
                                Erreur	C2065	'value' : identificateur non déclaré	odfaeg-core	C:\Users\Laurent\Windows\ODFAEG\include\odfaeg\Core\mp.hpp	13311	
                                Erreur	C2062	type 'unknown-type' inattendu	odfaeg-core	C:\Users\Laurent\Windows\ODFAEG\include\odfaeg\Core\mp.hpp	13311	
                                Erreur	C2146	erreur de syntaxe : absence de '>' avant l'identificateur 'type'	odfaeg-core	C:\Users\Laurent\Windows\ODFAEG\include\odfaeg\Core\mp.hpp	13311	
                                Erreur	C2062	type 'unknown-type' inattendu	odfaeg-core	C:\Users\Laurent\Windows\ODFAEG\include\odfaeg\Core\mp.hpp	13312	
                                Erreur	C2143	erreur de syntaxe : absence de ';' avant '}'	odfaeg-core	C:\Users\Laurent\Windows\ODFAEG\include\odfaeg\Core\mp.hpp	13315	
                                Erreur	C2238	jetons inattendus avant ';'	odfaeg-core	C:\Users\Laurent\Windows\ODFAEG\include\odfaeg\Core\mp.hpp	13315	
                                Erreur	C2923	'jln::mp::detail::_one' : 'xs::value' n'est pas un argument de type modèle valide pour le paramètre 'x'	odfaeg-core	C:\Users\Laurent\Windows\ODFAEG\include\odfaeg\Core\mp.hpp	13335	
                                Erreur	C2988	impossible de reconnaître la définition/déclaration de modèle	odfaeg-core	C:\Users\Laurent\Windows\ODFAEG\include\odfaeg\Core\mp.hpp	13335	
                                
                                
                                



                                -
                                Edité par OmbreNoire 5 juin 2021 à 7:17:34

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  5 juin 2021 à 7:44:41

                                  TDM-gcc32 est réputé moisi. De mémoire, ca utilise une vieille version de GCC. La doc dit que c'est basé sur C99.

                                  J'ai testé avec GCC et Clang, les calculs sont corrects.

                                  wikipedia a écrit:

                                  MinGW links by default to the Windows OS component library MSVCRT, which is the C library that Visual C++ version 6.0 linked to (the initial target was CRTDLL), which was released in 1998 and therefore does not include support for C99 features, or even all of C89. While targeting MSVCRT yields programs that require no additional runtime redistributables to be installed, the lack of support for C99 has caused porting problems, particularly where printf-style conversion specifiers are concerned. These issues have been partially mitigated by the implementation of a C99 compatibility library, libmingwex, but the extensive work required is far from complete and may never be fully realized.[10] Mingw-w64 has resolved these issues, and provides fully POSIX compliant printf functionality.

                                  Utilise MSVC. Ou mingw64. Mais pas TDM-gcc32.

                                  Ca te pose pas de problème que MSVC te retourne autant d'erreurs ?

                                  -
                                  Edité par gbdivers 5 juin 2021 à 7:45:35

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    5 juin 2021 à 8:01:00

                                    gbdivers a écrit:

                                    TDM-gcc32 est réputé moisi. De mémoire, ca utilise une vieille version de GCC. La doc dit que c'est basé sur C99.

                                    J'ai testé avec GCC et Clang, les calculs sont corrects.

                                    wikipedia a écrit:

                                    MinGW links by default to the Windows OS component library MSVCRT, which is the C library that Visual C++ version 6.0 linked to (the initial target was CRTDLL), which was released in 1998 and therefore does not include support for C99 features, or even all of C89. While targeting MSVCRT yields programs that require no additional runtime redistributables to be installed, the lack of support for C99 has caused porting problems, particularly where printf-style conversion specifiers are concerned. These issues have been partially mitigated by the implementation of a C99 compatibility library, libmingwex, but the extensive work required is far from complete and may never be fully realized.[10] Mingw-w64 has resolved these issues, and provides fully POSIX compliant printf functionality.

                                    Utilise MSVC. Ou mingw64. Mais pas TDM-gcc32.

                                    Ca te pose pas de problème que MSVC te retourne autant d'erreurs ?

                                    -
                                    Edité par gbdivers il y a 13 minutes

                                    Si, surtout que je n'ai pas ces erreurs sous mingw, je vais essayer avec mingw ça devrait mieux fonctionner. 

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      5 juin 2021 à 15:28:42

                                      Ok avec 32 ça ne résoud pas le problème le calcul est toujours mauvais je vais essayer en 64 bits.
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        8 juin 2021 à 10:04:58

                                        J'ai essayé avec mingw-W64 mais le résultat du calcul n'est toujours pas bon, je vais essayer sous visual studio, mais avant, je dois terminer de finir de réimplémenter le fichier mp.h de jonathan qui ne compile pas sous visual studio et je pense qu'il n'est pas bon non plus.
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          9 juin 2021 à 1:31:41

                                          mingw32, mingw64, VS .................... tu vas en essayer combien ????

                                          Et quand tu distribuera ton appli, tu imposera le compilateur aussi ? Ca ne va pas plaire à tous le monde.

                                          Ce n'est pas le compilateur qui est en cause, un code bien pensé compile sur toutes les plateformes, quelque soit le compilateur.
                                          La seule contrainte est que la version de C++ utilisée soit supportée par le compilateur.

                                          PS: Le meilleur moyen de tracker une variable, c'est de faire du pas à pas, et mettre des espions.

                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            9 juin 2021 à 1:35:46

                                            Deedolith a écrit:

                                            mingw32, mingw64, VS .................... tu vas en essayer combien ????

                                            Et quand tu distribuera ton appli, tu imposera le compilateur aussi ? Ca ne va pas plaire à tous le monde.

                                            Ce n'est pas le compilateur qui est en cause, un code bien pensé compile sur toutes les plateformes, quelque soit le compilateur.
                                            La seule contrainte est que la version de C++ utilisée soit supportée par le compilateur.

                                            PS: Le meilleur moyen de tracker une variable, c'est de faire du pas à pas, et mettre des espions.


                                            Je vais en essayer plusieurs, jusqu'à que j'en trouve un qui compile et exécute le code correctement. (Je vais essayer clang)

                                            Désolé mais je ne peux pas travailler avec des outils qui ne fonctionnent pas donc oui il se peut que j'impose un compilateur.

                                            -
                                            Edité par OmbreNoire 9 juin 2021 à 1:36:37

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              9 juin 2021 à 1:43:54

                                              Comme je t'ai dit dans l'autre discussion, il y a des erreurs dans le code que tu as donné (et que j'ai du corriger pour compiler). Le problème n'est pas que les compilateurs ne fonctionnent pas, c'est que ton code est incorrect.

                                              -
                                              Edité par gbdivers 9 juin 2021 à 1:44:14

                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                9 juin 2021 à 2:21:34

                                                > Désolé mais je ne peux pas travailler avec des outils qui ne fonctionnent pas donc oui il se peut que j'impose un compilateur.

                                                On en est à du haut niveau de troll, là...
                                                GCC (ben oui, mingw32-64 c'est GCC), Clang, et MSVC sont des compilos utilisés dans des dizaines de milliers de projets, t'inquiète pas qu'ils sont éprouvés et qu'ils fonctionnent (ils sont pas exempts de bugs, hein, mais pas du niveau de ce que tu as).

                                                Pour me mettre au même niveau de troll que toi, je pense que tu devrais éviter de travailler avec ton framework :p

                                                • Partager sur Facebook
                                                • Partager sur Twitter

                                                Si vous ne trouvez plus rien, cherchez autre chose.

                                                  10 juin 2021 à 9:52:51

                                                  Est-ce que quelqu'un est en mesure de comprendre ce code ? J'ai l'impression de lire les entrailles d'un header boost...
                                                  • Partager sur Facebook
                                                  • Partager sur Twitter

                                                  git is great because Linus did it, mercurial is better because he didn't.

                                                    11 juin 2021 à 16:46:34

                                                    markand a écrit:

                                                    Est-ce que quelqu'un est en mesure de comprendre ce code ? J'ai l'impression de lire les entrailles d'un header boost...


                                                    Tiens voilà pour toi! C'est plus clair ce code ? Il est plus lent que celui de fichier mp.hpp de Jonathan à cause de l'instanciation des std::tuples, mais, moins sal donc moins susceptible de planter, ça résoudra peut être le plantage que j'ai avec la nouvelle implémentation du delegate.

                                                    template <size_t SIZE, typename T>
                                                    struct placeholder {
                                                        static size_t constexpr size = SIZE;
                                                        using size_type = size_t;
                                                        using type = T;
                                                    };
                                                    template<class T>
                                                    struct is_placeholder
                                                    : std::false_type
                                                    {};
                                                    
                                                    template<std::size_t I, class T>
                                                    struct is_placeholder<placeholder<I, T>>
                                                    : std::true_type
                                                    {};
                                                    template<std::size_t N, typename Seq> struct offset_sequence;
                                                    
                                                    template<std::size_t N, std::size_t... Ints>
                                                    struct offset_sequence<N, std::index_sequence<Ints...>>
                                                    {
                                                     using type = std::index_sequence<Ints + N...>;
                                                    };
                                                    template<std::size_t N, typename Seq>
                                                    using offset_sequence_t = typename offset_sequence<N, Seq>::type;
                                                    template <size_t O, size_t N, size_t... Ints>
                                                    std::index_sequence<Ints...> make_offset_sequence () {
                                                        return offset_sequence_t<O, std::make_index_sequence<N>>::type();
                                                    }
                                                    template<typename Seq1, typename Seq> struct cat_sequence;
                                                    template<std::size_t... Ints1, std::size_t... Ints2>
                                                    struct cat_sequence<std::index_sequence<Ints1...>,
                                                                        std::index_sequence<Ints2...>>
                                                    {
                                                     using type = std::index_sequence<Ints1..., Ints2...>;
                                                    };
                                                    template<typename Seq1, typename Seq2>
                                                    using cat_sequence_t = typename cat_sequence<Seq1, Seq2>::type;
                                                    template<typename T, std::size_t... Ints>
                                                    auto select_tuple(std::index_sequence<Ints...>)
                                                    {
                                                     T tuple;
                                                     return std::tuple<T>();
                                                    }
                                                    template<std::size_t N, typename T>
                                                    auto remove_Nth()
                                                    {
                                                      constexpr auto size = std::tuple_size_v<T>;
                                                      using first = std::make_index_sequence<N>;
                                                      using rest = offset_sequence_t<N+1,
                                                                    std::make_index_sequence<size-N-1>>;
                                                      using indices = cat_sequence_t<first, rest>;
                                                      return select_tuple<T>(indices{});
                                                    }
                                                    template<template<class> class Pred, template <class...> class R>
                                                    struct append_if {
                                                        template <size_t I, class T, class... D, class = typename std::enable_if<Pred<decltype(std::get<I>(T()))>::value>::type>
                                                        static constexpr auto get() /*-> decltype(push_front<R,A, xs...>::type())*/{
                                                            return T();
                                                        }
                                                        template <size_t I, class T, class = typename std::enable_if<!Pred<decltype(std::get<I>(T()))>::value>::type>
                                                        static constexpr auto get() /*-> decltype(R<xs...>())*/ {
                                                            return remove_Nth<I, T>();
                                                        }
                                                        template <size_t I=0, class T, class... D, class = typename std::enable_if<(I == std::tuple_size<T>())>::type>
                                                        static constexpr auto f() /*-> decltype(get<decltype(std::get<Ints>(T())())...>())*/ {
                                                            return get<I-1, T>();
                                                        }
                                                        template <size_t I=0, class T, class... D, class... E, class = typename std::enable_if<(I != 0 && I != std::tuple_size<T>())>::type>
                                                        static constexpr auto const f() /*-> decltype(get<decltype(std::get<Ints>(T())())...>())*/ {
                                                            return get<I-1, T>();
                                                        }
                                                        template <size_t I=0, class T, class... D, class...E, class... F, class = typename std::enable_if<(I == 0)>::type>
                                                        static constexpr auto f() /*-> decltype(f<I+1>(std::make_index_sequence<std::tuple_size<T>()-I>()))*/ {
                                                            return f<I+1, T>();
                                                        }
                                                    };
                                                    template<template <class> class Pred, typename T, template <class> class R>
                                                    struct copy_if {
                                                        using f = decltype(append_if<Pred, R>::template f<0, T>());
                                                    };
                                                    /*template<class T, template <class> class R>
                                                    struct make_unique {
                                                        template <typename A, class... xs>
                                                        //requires std::derived_from<Pred<A>, std::true_type>
                                                        static constexpr auto get() -> decltype(push_front<R,A, xs...>::type()){
                                                            return push_front<R,A, xs...>::type();
                                                        }
                                                        /*template <typename A, class... xs>
                                                        requires std::derived_from<Pred<A>, std::false_type>
                                                        static constexpr auto get() -> decltype(std::tuple<xs...>()) {
                                                            return std::tuple<A, xs...>();
                                                        }*/
                                                        /*template <size_t I=0, size_t... Ints>
                                                        requires (I == std::tuple_size<T>())
                                                        static constexpr auto func(std::index_sequence<Ints...>) -> decltype(get<decltype(std::get<Ints+I-1>(T())())...>()) {
                                                            return get<decltype(std::get<Ints+I-1>(T())())...>();
                                                    
                                                        }
                                                        template <size_t I=0, size_t... Ints>
                                                        requires (I > 0 && I != std::tuple_size<T>())
                                                        static constexpr auto const func(std::index_sequence<Ints...>) -> decltype(get<decltype(std::get<Ints+I-1>(T())())...>()) {
                                                            return get<decltype(std::get<Ints+I-1>(T())())...>();
                                                        }
                                                        template <size_t I=0, size_t... Ints>
                                                        requires (I == 0)
                                                        static constexpr auto func(std::index_sequence<Ints...>) -> decltype(func<I+1>(std::make_index_sequence<std::tuple_size<T>()-I>())) {
                                                            return func<I+1>(std::make_index_sequence<std::tuple_size<T>()-I>());
                                                        }
                                                    };
                                                    template<class L, template <class> class R>
                                                    struct unique {
                                                        using f = decltype(make_unique<L, R>::func(std::make_index_sequence<std::tuple_size<L>()-0>()));
                                                    };*/
                                                    int main(int argc, char* argv[])
                                                    {
                                                        using late_params_t
                                                                  = copy_if<is_placeholder,std::tuple<placeholder<3, int>, float, placeholder<2, int>, int, placeholder<1, int>, char, placeholder<0, int>>, std::tuple>::f;
                                                        std::cout<<typeid(late_params_t).name()<<std::endl;
                                                    
                                                        return 0;

                                                    Mais avant je dois encore faire les fonctions uniques et sort, personnellement j'aime bien ça fait un bon exercice pour l'apprentissage de la méta programmation et moins compliqué que le fichier mp.hpp qui est inaccessible pour ceux qui n'ont jamais fait de méta programmation.

                                                    • Partager sur Facebook
                                                    • Partager sur Twitter

                                                    Plantage, copie du pointeur this.

                                                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                    • Editeur
                                                    • Markdown