Partage
  • Partager sur Facebook
  • Partager sur Twitter

static_cast foireux.

Adresses différentes du pointeur (dans le tuple et hors du tuple)

    4 juin 2021 à 23:37:10

    Le truc c'est que le problème avec void* c'est que je ne connais pas la taille des données individuellement stockées et apparemment ce n'est pas la même, même si c'est un tableau sur void*, je peux avoir une première donnée sur 8 octets et une autre sur 4 octets.

    La taille des octets là ou ça plante vaut 14 ce qui n'est pas un multiple ni de 4, ni de 8.

    Pas moyen de l'afficher ici donc pour retrouver la valeur de l'addresse :

     FastDelegate(FastDelegate& rhs)
               : data([&]{
                void* tab1 = nullptr;
                if (rhs.data.storage != nullptr) {
                    tab1 = new char[rhs.data.storage_size];
                    memcpy(tab1, rhs.data.storage, rhs.data.storage_size);
                }
                char* input = (char*) rhs.data.storage;
    
                std::cout<<"size : "<<rhs.data.storage_size<<std::endl;
                for (unsigned int i = 0; i < rhs.data.storage_size/4; i++) {
                  int first, second;
    
                  int startOffset = i * 4;
                    // 0x00000000 00000000
                  bool uint64=false;
                  bool isLittleEndian;
                  #ifdef WORDS_BIGENDIAN
                        isLittleEndian = false;
                  #else
                        isLittleEndian = true;
                  #endif
                  if (uint64) {
                      uint64_t adr;
                      if(isLittleEndian){       // MSB is loacted in higher address.
                        first = (input[startOffset]) | (input[startOffset+1] << 8) |
                          (input[startOffset+2] << 16) | (input[startOffset+3] << 24);
                        second = (input[startOffset+4]) | (input[startOffset+5] << 8) |
                          (input[startOffset+6] << 16) | (input[startOffset+7] << 24);
                        adr = (uint64_t) ((int64_t)((uint32_t) first | ((uint64_t) second << 32)));
                      }
                      else {                    // MSB is located in lower address.
                        first = (input[startOffset] << 24) | (input[startOffset+1] << 16) |
                          (input[startOffset+2] << 8) | (input[startOffset+3]);
                        second = (input[startOffset+4] << 24) | (input[startOffset+5] << 16) |
                          (input[startOffset+6] << 8) | (input[startOffset+7]);
                        adr = (uint64_t) ((int64_t)((uint32_t) second | (uint64_t) first << 32));
                      }
                      std::cout<<"src address : "<<std::hex<<adr<<std::endl;
                  } else {
                      // 0x00000000
                      uint32_t adr;
                      if(isLittleEndian){       // MSB is loacted in higher address.
                        adr = (uint32_t) (input[startOffset]) | (input[startOffset+1] << 8) |
                          (input[startOffset+2] << 16) | (input[startOffset+3] << 24);
                      }
                      else {                    // MSB is located in lower address.
                        adr = (uint32_t) (input[startOffset] << 24) | (input[startOffset] << 16) |
                          (input[startOffset] << 8) | (input[startOffset]);
                      }
                      std::cout<<"src address : "<<std::hex<<adr<<std::endl;
                  }
                }
                char* output = (char*) tab1;
                for (unsigned int i = 0; i < rhs.data.storage_size/4; i++) {
                    int first, second;
    
                  int startOffset = i * 4;
                    // 0x00000000 00000000
                  bool uint64=false;
                  bool isLittleEndian;
                  #ifdef WORDS_BIGENDIAN
                        isLittleEndian = false;
                  #else
                        isLittleEndian = true;
                  #endif
                  if (uint64) {
                      uint64_t adr;
                      if(isLittleEndian){       // MSB is loacted in higher address.
                        first = (output[startOffset]) | (output[startOffset+1] << 8) |
                          (output[startOffset+2] << 16) | (output[startOffset+3] << 24);
                        second = (output[startOffset+4]) | (output[startOffset+5] << 8) |
                          (output[startOffset+6] << 16) | (output[startOffset+7] << 24);
                        adr = (uint64_t) ((int64_t)((uint32_t) first | ((uint64_t) second << 32)));
                      }
                      else {                    // MSB is located in lower address.
                        first = (output[startOffset] << 24) | (output[startOffset+1] << 16) |
                          (output[startOffset+2] << 8) | (output[startOffset+3]);
                        second = (output[startOffset+4] << 24) | (output[startOffset+5] << 16) |
                          (output[startOffset+6] << 8) | (output[startOffset+7]);
                        adr = (uint64_t) ((int64_t)((uint32_t) second | (uint64_t) first << 32));
                      }
                      std::cout<<"dst address : "<<std::hex<<adr<<std::endl;
                  } else {
                      // 0x00000000
                      uint32_t adr;
                      if(isLittleEndian){       // MSB is loacted in higher address.
                        adr = (uint32_t) (output[startOffset]) | (output[startOffset+1] << 8) |
                          (output[startOffset+2] << 16) | (output[startOffset+3] << 24);
                      }
                      else {                    // MSB is located in lower address.
                        adr = (uint32_t) (output[startOffset] << 24) | (output[startOffset] << 16) |
                          (output[startOffset] << 8) | (output[startOffset]);
                      }
                      std::cout<<"dst address : "<<std::hex<<adr<<std::endl;
                  }
                }
                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 = nullptr;
                    if (rhs.data.storage != nullptr) {
                        tab1 = new char[rhs.data.storage_size];
                        memcpy(tab1, rhs.data.storage, rhs.data.storage_size);
                    }
                    /*char* src = (char*) rhs.data.storage;
                    char* dst = (char*) tab1;
                    for (unsigned int i = 0; i < rhs.data.storage_size; i++) {
                        std::cout<<" src"<<(int) src[i]<<std::endl;
                    }
                    for (unsigned int i = 0; i < rhs.data.storage_size; i++) {
                        std::cout<<" drc"<<(int) dst[i]<<std::endl;
                    }*/
                    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;
                }

    Pour ça que je n'aime pas la solution de jo-link (il ne répond plus d'ailleurs) parce que c'est très difficile à débuguer. Cependant les données en input et output sont les même donc memcpy fonctionne.

    Ou alors je dois aligner toutes les données sur la taille la plus grande (8 ici). 

    Malheureusement je ne sais pas comment faire cela.

    -
    Edité par OmbreNoire 4 juin 2021 à 23:43:59

    • Partager sur Facebook
    • Partager sur Twitter
      5 juin 2021 à 1:04:56

      A tout hasard je rappelle que:

      > If the objects are potentially-overlapping or not TriviallyCopyable, the behavior of memcpy is not specified and may be undefined.
      -- https://en.cppreference.com/w/cpp/string/byte/memcpy

      • Partager sur Facebook
      • Partager sur Twitter
      C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
        5 juin 2021 à 1:24:25

        Ah oui, la classe entity n'est pas "trivialy copyable" car elle n'est même pas copiable, peut être pour ça que ça plante, que doit je faire, copier moi même en utilisant des tableaux de char ?Utiliser memmove ?

        Je pensais que memcpy convertissait simplement void* en char* et faisait une copie octets par octets au pire je peux faire ça pour voir...

        • Partager sur Facebook
        • Partager sur Twitter
          5 juin 2021 à 2:35:53

          > Ah oui, la classe entity n'est pas "trivialy copyable" car elle n'est même pas copiable, peut être pour ça que ça plante, que doit je faire, copier moi même en utilisant des tableaux de char ?Utiliser memmove ?

          Ce qui est drôle est que tu ne comprends même pas les réponses qu'on te donne: une copie octet par octet ne fonctionnera pas. Ce qui t'amène à faire des suppositions qui n'ont aucun sens.

          Mais comme tes 10 ans de bouteille te permettent de faire des systèmes très complexes qui fonctionnent bien mieux que par exemple Boost.Serialization, je ne doute pas un instant que tu aies immédiatement compris ma petite implémentation de FastDelegate et qu'il me sera impossible de faire quelque chose si même toi n'y arrive pas !

          Je comprends parfaitement que tu aies ignoré une fois de plus ma dernière intervention, je suis navré d'avoir proposé un code trop simple bien en dessous de la qualité des tiens. J'espère que tu pardonneras aussi les autres intervenants (moi comprit) qui sont dans l'incapacité de comprendre pourquoi std::function n'est pas une solution viable.

          • Partager sur Facebook
          • Partager sur Twitter
            5 juin 2021 à 19:26:42

            jo_link_noir a écrit:

            > Ah oui, la classe entity n'est pas "trivialy copyable" car elle n'est même pas copiable, peut être pour ça que ça plante, que doit je faire, copier moi même en utilisant des tableaux de char ?Utiliser memmove ?

            Ce qui est drôle est que tu ne comprends même pas les réponses qu'on te donne: une copie octet par octet ne fonctionnera pas. Ce qui t'amène à faire des suppositions qui n'ont aucun sens.

            Mais comme tes 10 ans de bouteille te permettent de faire des systèmes très complexes qui fonctionnent bien mieux que par exemple Boost.Serialization, je ne doute pas un instant que tu aies immédiatement compris ma petite implémentation de FastDelegate et qu'il me sera impossible de faire quelque chose si même toi n'y arrive pas !

            Je comprends parfaitement que tu aies ignoré une fois de plus ma dernière intervention, je suis navré d'avoir proposé un code trop simple bien en dessous de la qualité des tiens. J'espère que tu pardonneras aussi les autres intervenants (moi comprit) qui sont dans l'incapacité de comprendre pourquoi std::function n'est pas une solution viable.

            Finalement je ne pense pas que c'est la copie, j'ai la même chose à la source et à la destination, c'est la source qui n'est pas bonne, j'ai fais un test de calcul au niveau du compilateur, parce que je trouvais ça louche que ça plante aléatoirement, j'ai changé de compilateur pour utiliser mingw-w64, mais, ça ne résous pas le problème, le résultat du calcul n'est pas bon donc le problème c'est ici :

            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),
                          0
                        };
                      }())


            Comme on peut le voir sur l'image le résultat du calcul n'est pas bon dans la lambda expression, 28/8 ça ne fait pas 5 et 8 * 5 ça ne fait pas 28.

            Apparemment sous visual studio 2019 ça fonctionne mais moi j'ai un tas d'erreurs de compilation avec le fichier mp.h. (Pourtant l'option c++17 à l'air d'être reconnu avec cmake)

            Ce que je comprends pas c'est que vous arriver à compiler du code sous visual studio que chez moi il ne compile pas.



            -
            Edité par OmbreNoire 5 juin 2021 à 19:31:26

            • Partager sur Facebook
            • Partager sur Twitter
              5 juin 2021 à 20:09:30

              > ça plante aléatoirement

              Il faudrait que tu te documentes sérieusement sur les UB

              - un résumé récent pas trop mal: https://queue.acm.org/detail.cfm?id=3468263

              - 3 articles, limite de référence, chez John Regehr: https://www.cs.utah.edu/~regehr/

              A compléter éventuellement par les sections sur l'utilisation de zones mémoire non construites, et autres type punning que ne manquent pas de m'évoquer ces memcpy dans un domaine qui devrait se résumer à du type erasing d'objets fonctions.

              • Partager sur Facebook
              • Partager sur Twitter
              C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                8 juin 2021 à 10:01:19

                Salut! Je pense que le fichier mp.hpp de jonathan n'est pas bon déjà, pas moyen de tester dans le main j'ai réécris la fonction copy_if, et j'ai essayer de l'utiliser avec unique du fichier.h mais ça ne retire pas les doublons :

                struct identity {
                    template <class x>
                    using type = x;
                };
                template <class... A>
                struct list {
                };
                template <class L> struct _unpack {};
                template <class L> struct _push_front {};
                template<class C>
                struct unpack {
                    template<class seq, class... xs>
                    using f = typename _unpack<seq>::template f<C, xs...>;
                
                };
                template <template <class...> class L, class A, class... Args>
                struct push_front {
                    using type = L<A, Args...>;
                };
                template<template<class...> class F, class C=identity>
                struct lift
                {
                    template<class... xs>
                    using f = typename C::template f<F, xs...>;
                };
                template<template<class...> class F>
                struct lift<F, identity>
                {
                    template<class... xs>
                    using f = F<xs...>;
                };
                template<class C, template<class> class Pred, template <class...> class R>
                struct append_if {
                    template <typename A, class... xs>
                    requires std::derived_from<Pred<A>, std::true_type>
                    static push_front<R, A, xs...>::type const get() {
                
                    }
                    template <typename A, class... xs>
                    requires std::derived_from<Pred<A>, std::false_type>
                    static R<A, xs...> const get() {
                
                    }
                    template <size_t I, size_t S, class A, class... xs>
                    requires (I == 0)
                    static auto func() -> decltype(get<A, xs...>()) {
                        //std::cout<<"I = 0 : "<<I<<std::endl;
                
                    }
                    template <size_t I, size_t S, class L, class A, class... xs>
                    requires (I != S-1 && I > 0)
                    static constexpr auto const func() -> decltype(get<A, xs...>()) {
                        //std::cout<<"I != S-1 : "<<I<<std::endl;
                        //return func<I-1, S, decltype(get<A, seq>()), xs...>();
                    }
                    template <size_t I, size_t S, class A, class... xs>
                    requires (I == S-1)
                    static constexpr auto func() -> decltype(func<I-1, S, decltype(get<A, xs...>()), xs...>()) {
                        //std::cout<<"I = S-1 : "<<I<<std::endl;
                        //return func<I-1, S, decltype(get<A, list<>>()), xs...>();
                    }
                };
                template<template <class> class Pred, typename C, template <class> class R>
                struct copy_if {
                    template <class... xs>
                    using f = decltype(append_if<C, Pred, R>::template func<sizeof...(xs)-1, sizeof...(xs), xs...>());
                };
                
                
                
                
                template<class Cmp, class C>
                struct mk_unique;
                template<class C>
                struct unique {
                    using f = typename mk_unique<lift<std::is_same>, C>::type;
                };
                template<int n, class Cmp>
                struct _sort;
                
                /// \endcond
                
                /// \ingroup algorithm
                
                /// Sorts the elements of a \sequence according to an ordering relation.
                /// \post \c is_sorted<result...>
                /// \treturn \sequence
                template<class Cmp, class C>
                struct sort
                {
                    template<class... xs>
                    using f = typename unpack<C>::template f<
                        typename _sort<sizeof...(xs), Cmp>
                        ::template f<xs...>
                    >;
                };
                int main(int argc, char* argv[])
                {
                
                
                    using late_params_t
                              = copy_if<is_placeholder,unique<sort<LessPlaceceholder,
                                                                lift<LateParameters>>>, LateParameters>
                                ::f<int, placeholder<3, int>, placeholder<2, int>,placeholder<0, int>,placeholder<0, int>>;
                    std::cout<<typeid(late_params_t).name()<<std::endl;

                Ca me met une erreur en compilation comme quoi placeholder<0, int> à été défini 2 fois et sort ne trie rien (j'ai peut être pas mit tout le code du fichier mp.h il utilise peut être d'autres struct je n'en sais rien)

                Bref c'est un peu le bazard ce fichier, j'ai dû implémenter copy_if d'une manière plus compréhensible pour moi, je pense que je vais devoir aussi réimplémenter unique parce que ça me semble étrange parce que normalement il faut faire la récursion, sur tout les types, vérifier si il n'est pas déjà dans la liste avec is_same et si pas, l'ajouter.

                Avec sort il faut faire deux boucles et permuter les éléments.



                • Partager sur Facebook
                • Partager sur Twitter
                  8 juin 2021 à 10:20:58

                  « J'ai refait copy_if et n'ai pas réussi à copier le contenu de unique.hpp ni de sort.hpp. Ça ne marche pas, c'est la faute à Jonathan »

                  :')

                  • Partager sur Facebook
                  • Partager sur Twitter
                    11 juin 2021 à 13:19:51

                    jo_link_noir a écrit:

                    « J'ai refait copy_if et n'ai pas réussi à copier le contenu de unique.hpp ni de sort.hpp. Ça ne marche pas, c'est la faute à Jonathan »

                    :')


                    Je ne comprend pas pourquoi tu n'as pas utiliser les tuples plutôt que ce code de bourrin du fichier mp.hpp ça aurait été beaucoup moins galère ;) :

                    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 <template <class...> class L, class A, class... Args>
                    struct push_front {
                        using type = L<A, Args...>;
                    };
                    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 T, std::size_t... Ints>
                    auto select_tuple(std::index_sequence<Ints...>)
                    {
                     T tuple;
                     return std::make_tuple(
                        std::get<Ints>(std::forward<T>(tuple))...);
                    }
                    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>>;
                      return std::tuple_cat(
                        select_tuple<T>(first{}),
                        select_tuple<T>(rest{}));
                    }
                    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>());
                    };
                     
                    int main(int argc, char* argv[])
                    {
                        using late_params_t
                                  = copy_if<is_placeholder,std::tuple<double, 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; }
                    Il me reste plus qu'à faire de même pour l'implémentation de unique et de sort. 

                    -
                    Edité par OmbreNoire 11 juin 2021 à 13:21:03

                    • Partager sur Facebook
                    • Partager sur Twitter
                      11 juin 2021 à 14:43:51

                      > Je ne comprend pas pourquoi tu n'as pas utiliser les tuples plutôt que ce code de bourrin du fichier mp.hpp ça aurait été beaucoup moins galère ;) :

                      Déjà expliqué: pour des raisons de performance au niveau du temps de compilation et de la mémoire utilisé par le compilo. De plus, std::tuple impose que les types soit instanciable, ce qui n'est pas mon cas. Comment mets-tu un void dans un tuple ?

                      Ta version:

                      • 0:00.56s - 106396K

                      Avec jln.mp (donc juste changer le main):

                      • 0:00.51s - 96408K

                      (En sachant que ce qui prend le plus de temps ici sont les includes)

                      Au passage, ta version ne fonctionne toujours pas: std::tuple<placeholder<3, int>, float, placeholder<2, int>, int, placeholder<1, int>, char, placeholder<0, int> >.

                      À dans 1 semaine

                      -
                      Edité par jo_link_noir 11 juin 2021 à 14:45:50

                      • Partager sur Facebook
                      • Partager sur Twitter
                        11 juin 2021 à 15:36:42

                        jo_link_noir a écrit:

                        > Je ne comprend pas pourquoi tu n'as pas utiliser les tuples plutôt que ce code de bourrin du fichier mp.hpp ça aurait été beaucoup moins galère ;) :

                        Déjà expliqué: pour des raisons de performance au niveau du temps de compilation et de la mémoire utilisé par le compilo. De plus, std::tuple impose que les types soit instanciable, ce qui n'est pas mon cas. Comment mets-tu un void dans un tuple ?

                        Ta version:

                        • 0:00.56s - 106396K

                        Avec jln.mp (donc juste changer le main):

                        • 0:00.51s - 96408K

                        (En sachant que ce qui prend le plus de temps ici sont les includes)

                        Au passage, ta version ne fonctionne toujours pas: std::tuple<placeholder<3, int>, float, placeholder<2, int>, int, placeholder<1, int>, char, placeholder<0, int> >.

                        À dans 1 semaine

                        -
                        Edité par jo_link_noir il y a 42 minutes


                        Si je pense que elle fonctionne c'est typeid qui n'affiche pas tout les types lorsque le premier est un placeholder parce que je renvoie le tuple lui même lorsque le tuple contient un placeholder donc ça m'étonnerait qu'il m'enlève un élément tout seul si je n'en supprime pas lorsque par exemple je n'ai que des placeholders. Par contre la performance personnellement je n'en ai pas besoin lors de l'instanciation, seulement lors du rendu. C'est la simplicité que je recherche. Avec ton code je ne suis pas parvenu à afficher le type avec typeid.

                        EDIT : j'ai trouvé l'erreur, maintenant ça fonctionne!!!

                        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>());
                        };
                        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; }



                        -
                        Edité par OmbreNoire 11 juin 2021 à 16:37:12

                        • Partager sur Facebook
                        • Partager sur Twitter
                          11 juin 2021 à 18:17:48

                          > Si je pense que elle fonctionne c'est typeid qui n'affiche pas tout les types

                          Moi j'assure qu’elle ne fonctionne pas. Et ce n'est pas avec typeid qu'on fait des tests. Dans le pire des cas on passe par __PRETTY_FUNCTION__ pour savoir à quoi ça ressemble, mais pour avoir des tests un minimum explicite sur le type du résultat, on fait une bête instanciation.

                          template<class> struct type_ {};
                          
                          // dans une fonction
                          type_<late_params_t>() = type_<std::tuple<
                            placeholder<3, int>,
                            placeholder<2, int>,
                            placeholder<1, int>,
                            placeholder<0, int>
                          >>();
                          

                          Et on se rend bien compte que cela ne compile pas -> ton implémentation ne fonctionne pas.

                          Le projet dispose d'un mini framework de test, mais tu es incapable de regarder au-delà du premier lien.

                          -
                          Edité par jo_link_noir 11 juin 2021 à 18:18:26

                          • Partager sur Facebook
                          • Partager sur Twitter
                            11 juin 2021 à 18:38:57

                            jo_link_noir a écrit:

                            > Si je pense que elle fonctionne c'est typeid qui n'affiche pas tout les types

                            Moi j'assure qu’elle ne fonctionne pas. Et ce n'est pas avec typeid qu'on fait des tests. Dans le pire des cas on passe par __PRETTY_FUNCTION__ pour savoir à quoi ça ressemble, mais pour avoir des tests un minimum explicite sur le type du résultat, on fait une bête instanciation.

                            template<class> struct type_ {};
                            
                            // dans une fonction
                            type_<late_params_t>() = type_<std::tuple<
                              placeholder<3, int>,
                              placeholder<2, int>,
                              placeholder<1, int>,
                              placeholder<0, int>
                            >>();
                            

                            Et on se rend bien compte que cela ne compile pas -> ton implémentation ne fonctionne pas.

                            Le projet dispose d'un mini framework de test, mais tu es incapable de regarder au-delà du premier lien.

                            -
                            Edité par jo_link_noir il y a 12 minutes

                            Comment ça, ça ne fonctionne pas, typeid(type).name() m'affiche le bon type mais il faudrait en effet que j'essaie de l'instancier dans le main, pour voir.

                            • Partager sur Facebook
                            • Partager sur Twitter
                              11 juin 2021 à 19:16:36

                              Tester, c'est déjà douter.

                              • Partager sur Facebook
                              • Partager sur Twitter
                                11 juin 2021 à 22:27:32

                                En effet ça ne fonctionne pas, comme je le pensais au départ, déjà j'ai dû compter le nombre d'éléments supprimés parce que quand on supprime un élément ça décale et donc l'index n'est plus bon, ensuite ma récursion n'était pas bonne il faut appeler get dans f, cependant j'ai encore des erreurs ce que je voudrais faire c'est ceci :

                                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::tuple<placeholder<3, int>, float, placeholder<2, int>, int, placeholder<1, int>, char, placeholder<0, int>> tp;
                                    auto rtp = remove_Nth<1, decltype(tp)>();
                                    auto rtp2 = remove_Nth<2, decltype(rtp)>();
                                    auto rtp3 = remove_Nth<3, decltype(rtp2)>();
                                    std::cout<<typeid(late_params_t).name()<<std::endl;
                                    late_params_t t = std::make_tuple(placeholder<3, int>(), placeholder<2, int>(), placeholder<1, int>(), placeholder<0, int>());
                                    return 0;
                                }

                                Mais je ne sais pas si c'est possible du fait que le type renvoyé par remove_Nth est inconnu, enfin, dans le main il arrive à le déduire mais pas dans ma structure apparemment :

                                template<template<class> class Pred, template <class...> class R>
                                struct append_if {
                                    //If the type statisfy the condition we don't remove it and return the tuple itself.
                                    template <size_t I, size_t NB, class T, class... D, class = typename std::enable_if<Pred<decltype(std::get<I>(T()))>::value>::type>
                                    static auto get(T tp) {
                                        return tp;
                                    }
                                    //If the type doesn't satisfy the condition we remove it from the tuple and return the new tuple.
                                    //As a good surprise for me it works event if the type of the returned tuple is not the same as the type of the provided tuple.
                                    template <size_t I, size_t NB, class T, class = typename std::enable_if<!Pred<decltype(std::get<I>(T()))>::value>::type>
                                    static constexpr auto get(T tp) {
                                        //std::cout<<"I : "<<I<<std::endl;
                                        return remove_Nth<I, T>();
                                    }
                                    //final case : we stop recursion when we have browsed all the elements of the tuple and we check if the last element must be removed.
                                    template <size_t I=0, size_t NB, class T, class... D, class = typename std::enable_if<(I == std::tuple_size<T>() && Pred<decltype(std::get<I>(T()))>::value)>::type>
                                    static constexpr auto f(T tp) {
                                        return get<I-1, NB>(tp);
                                    }
                                    template <size_t I=0, size_t NB, class T, class... D, class... E, class = typename std::enable_if<(I == std::tuple_size<T>() && !Pred<decltype(std::get<I>(T()))>::value)>::type>
                                    static constexpr auto f(T tp) {
                                        return get<I-1, NB+1>(tp);
                                    }
                                    //Intermediate case : we check if the I-1 element of the tuple have to be removed or not, I-1 because we start at I+1.
                                    template <size_t I=0, size_t NB, class T, class... D, class... E, class... F, class = typename std::enable_if<(I != 0 && I != std::tuple_size<T>() && Pred<decltype(std::get<I>(T()))>::value)>::type>
                                    static constexpr auto f(T tp) {
                                        return f<I+1, NB, T>(get<I-1, NB>(tp));
                                    }
                                    //Intermediate case : we check if the I-1 element of the tuple have to be removed or not, I-1 because we start at I+1.
                                    template <size_t I=0, size_t NB, class T, class... D, class... E, class... F, class... G, class = typename std::enable_if<(I != 0 && I != std::tuple_size<T>() && !Pred<decltype(std::get<I>(T()))>::value)>::type>
                                    static constexpr auto f(T tp) {
                                        return f<I+1, NB+1>(get<I-1, NB+1>(tp));
                                    }
                                    template <size_t I=0, size_t NB, class T, class... D, class... E, class... F, class... G, class... H, class = typename std::enable_if<(I == 0)>::type>
                                    static constexpr auto f(T tp) {
                                        return f<I+1, 0>(tp);
                                    }
                                };

                                Ca me met un tas d'erreurs de ce genre :

                                ||=== Build: Release in ODFAEGCREATOR (compiler: GNU GCC Compiler) ===|
                                C:\Program Files (x86)\ODFAEG\include\odfaeg\Graphics\entity.h|373|warning: "/*" within comment [-Wcomment]|
                                C:\Program Files (x86)\ODFAEG\include\odfaeg\Graphics\entity.h|373|warning: "/*" within comment [-Wcomment]|
                                C:\Program Files (x86)\ODFAEG\include\odfaeg\Graphics\entity.h|373|warning: "/*" within comment [-Wcomment]|
                                C:\Program Files (x86)\ODFAEG\include\odfaeg\Graphics\entity.h|373|warning: "/*" within comment [-Wcomment]|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|2|warning: extra tokens at end of #include directive|
                                C:\Program Files (x86)\ODFAEG\include\odfaeg\Math\computer.h|418|warning: suggest parentheses around '&&' within '||' [-Wparentheses]|
                                C:\Program Files (x86)\ODFAEG\include\odfaeg\Math\computer.h|436|warning: comparison of integer expressions of different signedness: 'unsigned int' and 'int' [-Wsign-compare]|
                                C:\Program Files (x86)\ODFAEG\include\odfaeg\Window\iWindow.hpp||In member function 'virtual const odfaeg::window::ContextSettings& odfaeg::window::IWindow::getSettings() const':|
                                C:\Program Files (x86)\ODFAEG\include\odfaeg\Window\iWindow.hpp|193|warning: returning reference to temporary [-Wreturn-local-addr]|
                                C:\Program Files (x86)\ODFAEG\include\odfaeg\Graphics\lightComponent.h||In constructor 'odfaeg::graphic::LightComponent::LightComponent(odfaeg::graphic::RenderWindow&, odfaeg::math::Vec3f, odfaeg::math::Vec3f, odfaeg::math::Vec3f, unsigned int, odfaeg::graphic::LightComponent*)':|
                                C:\Program Files (x86)\ODFAEG\include\odfaeg\Graphics\lightComponent.h|180|warning: 'odfaeg::graphic::LightComponent::parent' will be initialized after [-Wreorder]|
                                C:\Program Files (x86)\ODFAEG\include\odfaeg\Graphics\lightComponent.h|179|warning:   'bool odfaeg::graphic::LightComponent::enableScissorTest' [-Wreorder]|
                                C:\Program Files (x86)\ODFAEG\include\odfaeg\Graphics\lightComponent.h|13|warning:   when initialized here [-Wreorder]|
                                C:\Program Files (x86)\ODFAEG\include\odfaeg\Graphics\lightComponent.h||In member function 'virtual void odfaeg::graphic::LightComponent::recomputeSize()':|
                                C:\Program Files (x86)\ODFAEG\include\odfaeg\Graphics\lightComponent.h|24|warning: unused variable 'sx' [-Wunused-variable]|
                                C:\Program Files (x86)\ODFAEG\include\odfaeg\Graphics\lightComponent.h|24|warning: unused variable 'sy' [-Wunused-variable]|
                                C:\Program Files (x86)\ODFAEG\include\odfaeg\Graphics\lightComponent.h|24|warning: variable 'ppx' set but not used [-Wunused-but-set-variable]|
                                C:\Program Files (x86)\ODFAEG\include\odfaeg\Graphics\lightComponent.h|24|warning: variable 'ppy' set but not used [-Wunused-but-set-variable]|
                                C:\Program Files (x86)\ODFAEG\include\odfaeg\Network\aes.h||In member function 'void odfaeg::network::AES_ENC::Xor(char*, const char*)':|
                                C:\Program Files (x86)\ODFAEG\include\odfaeg\Network\aes.h|180|warning: comparison of integer expressions of different signedness: 'int' and 'const unsigned int' [-Wsign-compare]|
                                C:\Program Files (x86)\ODFAEG\include\odfaeg\Network\network.h|191|warning: the compiler can assume that the address of 'odfaeg::network::Network::cli' will never be NULL [-Waddress]|
                                C:\Program Files (x86)\ODFAEG\include\odfaeg\Network\network.h|228|warning: the compiler can assume that the address of 'odfaeg::network::Network::srv' will never be NULL [-Waddress]|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple||In instantiation of 'struct std::tuple_element<0, std::tuple<> >':|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1285|  recursively required from 'struct std::tuple_element<3, std::tuple<int, char, placeholder<0, int> > >'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1285|required from 'struct std::tuple_element<4, std::tuple<float, int, char, placeholder<0, int> > >'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|114|  required by substitution of 'template<unsigned int __i, class _Tp> using __tuple_element_t = typename std::tuple_element::type [with unsigned int __i = 4; _Tp = std::tuple<float, int, char, placeholder<0, int> >]'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1341|  required by substitution of 'template<unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >&& std::get(const std::tuple<_Elements ...>&&) [with unsigned int __i = 4; _Elements = {float, int, char, placeholder<0, int>}]'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|104|  recursively required from 'static constexpr auto append_if<Pred, R>::f(T) [with unsigned int I = 2; unsigned int NB = 1; T = std::tuple<float, placeholder<2, int>, int, placeholder<1, int>, char, placeholder<0, int> >; D = {}; E = {}; F = {}; G = {}; <template-parameter-2-8> = void; Pred = is_placeholder; R = std::tuple]'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|104|required from 'static constexpr auto append_if<Pred, R>::f(T) [with unsigned int I = 1; unsigned int NB = 0; T = std::tuple<placeholder<3, int>, float, placeholder<2, int>, int, placeholder<1, int>, char, placeholder<0, int> >; D = {}; E = {}; F = {}; G = {}; <template-parameter-2-8> = void; Pred = is_placeholder; R = std::tuple]'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|108|required from 'static constexpr auto append_if<Pred, R>::f(T) [with unsigned int I = 0; unsigned int NB = 0; T = std::tuple<placeholder<3, int>, float, placeholder<2, int>, int, placeholder<1, int>, char, placeholder<0, int> >; D = {}; E = {}; F = {}; G = {}; H = {}; <template-parameter-2-9> = void; Pred = is_placeholder; R = std::tuple]'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|114|required from 'struct copy_if<is_placeholder, std::tuple<placeholder<3, int>, float, placeholder<2, int>, int, placeholder<1, int>, char, placeholder<0, int> >, std::tuple>'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|167|required from here|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1303|error: static assertion failed: tuple index is in range|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp||In instantiation of 'static constexpr auto append_if<Pred, R>::f(T) [with unsigned int I = 3; unsigned int NB = 2; T = std::tuple<float, int, placeholder<1, int>, char, placeholder<0, int> >; D = {}; E = {}; F = {}; G = {}; <template-parameter-2-8> = void; Pred = is_placeholder; R = std::tuple]':|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|104|  recursively required from 'static constexpr auto append_if<Pred, R>::f(T) [with unsigned int I = 2; unsigned int NB = 1; T = std::tuple<float, placeholder<2, int>, int, placeholder<1, int>, char, placeholder<0, int> >; D = {}; E = {}; F = {}; G = {}; <template-parameter-2-8> = void; Pred = is_placeholder; R = std::tuple]'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|104|required from 'static constexpr auto append_if<Pred, R>::f(T) [with unsigned int I = 1; unsigned int NB = 0; T = std::tuple<placeholder<3, int>, float, placeholder<2, int>, int, placeholder<1, int>, char, placeholder<0, int> >; D = {}; E = {}; F = {}; G = {}; <template-parameter-2-8> = void; Pred = is_placeholder; R = std::tuple]'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|108|required from 'static constexpr auto append_if<Pred, R>::f(T) [with unsigned int I = 0; unsigned int NB = 0; T = std::tuple<placeholder<3, int>, float, placeholder<2, int>, int, placeholder<1, int>, char, placeholder<0, int> >; D = {}; E = {}; F = {}; G = {}; H = {}; <template-parameter-2-9> = void; Pred = is_placeholder; R = std::tuple]'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|114|required from 'struct copy_if<is_placeholder, std::tuple<placeholder<3, int>, float, placeholder<2, int>, int, placeholder<1, int>, char, placeholder<0, int> >, std::tuple>'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|167|required from here|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|104|error: no matching function for call to 'append_if<is_placeholder, std::tuple>::f<(3 + 1), (2 + 1)>(std::tuple<float, int, char, placeholder<0, int> >)'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|89|note: candidate: 'template<unsigned int I, unsigned int NB, class T, class ... D, class> static constexpr auto append_if<Pred, R>::f(T) [with unsigned int I = I; unsigned int NB = NB; T = T; D = {D ...}; <template-parameter-2-5> = <template-parameter-1-5>; Pred = is_placeholder; R = std::tuple]'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|89|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|error: no matching function for call to 'get<4>(std::tuple<float, int, char, placeholder<0, int> >)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|219|note: candidate: 'template<unsigned int _Int, class _Tp1, class _Tp2> constexpr typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(std::pair<_Tp1, _Tp2>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|219|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|note:   'std::tuple<float, int, char, placeholder<0, int> >' is not derived from 'std::pair<_Tp1, _Tp2>'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|224|note: candidate: 'template<unsigned int _Int, class _Tp1, class _Tp2> constexpr typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type&& std::get(std::pair<_Tp1, _Tp2>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|224|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|note:   'std::tuple<float, int, char, placeholder<0, int> >' is not derived from 'std::pair<_Tp1, _Tp2>'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|229|note: candidate: 'template<unsigned int _Int, class _Tp1, class _Tp2> constexpr const typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(const std::pair<_Tp1, _Tp2>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|229|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|note:   'std::tuple<float, int, char, placeholder<0, int> >' is not derived from 'const std::pair<_Tp1, _Tp2>'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|234|note: candidate: 'template<unsigned int _Int, class _Tp1, class _Tp2> constexpr const typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type&& std::get(const std::pair<_Tp1, _Tp2>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|234|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|note:   'std::tuple<float, int, char, placeholder<0, int> >' is not derived from 'const std::pair<_Tp1, _Tp2>'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|243|note: candidate: 'template<class _Tp, class _Up> constexpr _Tp& std::get(std::pair<_T1, _T2>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|243|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|248|note: candidate: 'template<class _Tp, class _Up> constexpr const _Tp& std::get(const std::pair<_T1, _T2>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|248|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|253|note: candidate: 'template<class _Tp, class _Up> constexpr _Tp&& std::get(std::pair<_T1, _T2>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|253|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|258|note: candidate: 'template<class _Tp, class _Up> constexpr const _Tp&& std::get(const std::pair<_T1, _T2>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|258|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|263|note: candidate: 'template<class _Tp, class _Up> constexpr _Tp& std::get(std::pair<_Up, _Tp>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|263|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|268|note: candidate: 'template<class _Tp, class _Up> constexpr const _Tp& std::get(const std::pair<_Up, _Tp>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|268|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|273|note: candidate: 'template<class _Tp, class _Up> constexpr _Tp&& std::get(std::pair<_Up, _Tp>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|273|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|278|note: candidate: 'template<class _Tp, class _Up> constexpr const _Tp&& std::get(const std::pair<_Up, _Tp>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|278|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\array|307|note: candidate: 'template<unsigned int _Int, class _Tp, unsigned int _Nm> constexpr _Tp& std::get(std::array<_Tp, _Nm>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\array|307|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|note:   'std::tuple<float, int, char, placeholder<0, int> >' is not derived from 'std::array<_Tp, _Nm>'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\array|316|note: candidate: 'template<unsigned int _Int, class _Tp, unsigned int _Nm> constexpr _Tp&& std::get(std::array<_Tp, _Nm>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\array|316|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|note:   'std::tuple<float, int, char, placeholder<0, int> >' is not derived from 'std::array<_Tp, _Nm>'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\array|324|note: candidate: 'template<unsigned int _Int, class _Tp, unsigned int _Nm> constexpr const _Tp& std::get(const std::array<_Tp, _Nm>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\array|324|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|note:   'std::tuple<float, int, char, placeholder<0, int> >' is not derived from 'const std::array<_Tp, _Nm>'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\array|333|note: candidate: 'template<unsigned int _Int, class _Tp, unsigned int _Nm> constexpr const _Tp&& std::get(const std::array<_Tp, _Nm>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\array|333|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|note:   'std::tuple<float, int, char, placeholder<0, int> >' is not derived from 'const std::array<_Tp, _Nm>'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1320|note: candidate: 'template<unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >& std::get(std::tuple<_Elements ...>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1320|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1320|  required by substitution of 'template<unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >& std::get(std::tuple<_Elements ...>&) [with unsigned int __i = 4; _Elements = {float, int, char, placeholder<0, int>}]'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|104|  recursively required from 'static constexpr auto append_if<Pred, R>::f(T) [with unsigned int I = 2; unsigned int NB = 1; T = std::tuple<float, placeholder<2, int>, int, placeholder<1, int>, char, placeholder<0, int> >; D = {}; E = {}; F = {}; G = {}; <template-parameter-2-8> = void; Pred = is_placeholder; R = std::tuple]'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|104|required from 'static constexpr auto append_if<Pred, R>::f(T) [with unsigned int I = 1; unsigned int NB = 0; T = std::tuple<placeholder<3, int>, float, placeholder<2, int>, int, placeholder<1, int>, char, placeholder<0, int> >; D = {}; E = {}; F = {}; G = {}; <template-parameter-2-8> = void; Pred = is_placeholder; R = std::tuple]'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|108|required from 'static constexpr auto append_if<Pred, R>::f(T) [with unsigned int I = 0; unsigned int NB = 0; T = std::tuple<placeholder<3, int>, float, placeholder<2, int>, int, placeholder<1, int>, char, placeholder<0, int> >; D = {}; E = {}; F = {}; G = {}; H = {}; <template-parameter-2-9> = void; Pred = is_placeholder; R = std::tuple]'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|114|required from 'struct copy_if<is_placeholder, std::tuple<placeholder<3, int>, float, placeholder<2, int>, int, placeholder<1, int>, char, placeholder<0, int> >, std::tuple>'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|167|required from here|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|114|error: no type named 'type' in 'struct std::tuple_element<4, std::tuple<float, int, char, placeholder<0, int> > >'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp||In instantiation of 'static constexpr auto append_if<Pred, R>::f(T) [with unsigned int I = 3; unsigned int NB = 2; T = std::tuple<float, int, placeholder<1, int>, char, placeholder<0, int> >; D = {}; E = {}; F = {}; G = {}; <template-parameter-2-8> = void; Pred = is_placeholder; R = std::tuple]':|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|104|  recursively required from 'static constexpr auto append_if<Pred, R>::f(T) [with unsigned int I = 2; unsigned int NB = 1; T = std::tuple<float, placeholder<2, int>, int, placeholder<1, int>, char, placeholder<0, int> >; D = {}; E = {}; F = {}; G = {}; <template-parameter-2-8> = void; Pred = is_placeholder; R = std::tuple]'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|104|required from 'static constexpr auto append_if<Pred, R>::f(T) [with unsigned int I = 1; unsigned int NB = 0; T = std::tuple<placeholder<3, int>, float, placeholder<2, int>, int, placeholder<1, int>, char, placeholder<0, int> >; D = {}; E = {}; F = {}; G = {}; <template-parameter-2-8> = void; Pred = is_placeholder; R = std::tuple]'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|108|required from 'static constexpr auto append_if<Pred, R>::f(T) [with unsigned int I = 0; unsigned int NB = 0; T = std::tuple<placeholder<3, int>, float, placeholder<2, int>, int, placeholder<1, int>, char, placeholder<0, int> >; D = {}; E = {}; F = {}; G = {}; H = {}; <template-parameter-2-9> = void; Pred = is_placeholder; R = std::tuple]'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|114|required from 'struct copy_if<is_placeholder, std::tuple<placeholder<3, int>, float, placeholder<2, int>, int, placeholder<1, int>, char, placeholder<0, int> >, std::tuple>'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|167|required from here|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1326|note: candidate: 'template<unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >& std::get(const std::tuple<_Elements ...>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1326|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1332|note: candidate: 'template<unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >&& std::get(std::tuple<_Elements ...>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1332|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1341|note: candidate: 'template<unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >&& std::get(const std::tuple<_Elements ...>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1341|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1364|note: candidate: 'template<class _Tp, class ... _Types> constexpr _Tp& std::get(std::tuple<_Elements ...>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1364|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1370|note: candidate: 'template<class _Tp, class ... _Types> constexpr _Tp&& std::get(std::tuple<_Elements ...>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1370|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1376|note: candidate: 'template<class _Tp, class ... _Types> constexpr const _Tp& std::get(const std::tuple<_Elements ...>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1376|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1383|note: candidate: 'template<class _Tp, class ... _Types> constexpr const _Tp&& std::get(const std::tuple<_Elements ...>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1383|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|93|note: candidate: 'template<unsigned int I, unsigned int NB, class T, class ... D, class ... E, class> static constexpr auto append_if<Pred, R>::f(T) [with unsigned int I = I; unsigned int NB = NB; T = T; D = {D ...}; E = {E ...}; <template-parameter-2-6> = <template-parameter-1-6>; Pred = is_placeholder; R = std::tuple]'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|93|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|error: no matching function for call to 'get<4>(std::tuple<float, int, char, placeholder<0, int> >)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|219|note: candidate: 'template<unsigned int _Int, class _Tp1, class _Tp2> constexpr typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(std::pair<_Tp1, _Tp2>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|219|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|note:   'std::tuple<float, int, char, placeholder<0, int> >' is not derived from 'std::pair<_Tp1, _Tp2>'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|224|note: candidate: 'template<unsigned int _Int, class _Tp1, class _Tp2> constexpr typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type&& std::get(std::pair<_Tp1, _Tp2>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|224|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|note:   'std::tuple<float, int, char, placeholder<0, int> >' is not derived from 'std::pair<_Tp1, _Tp2>'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|229|note: candidate: 'template<unsigned int _Int, class _Tp1, class _Tp2> constexpr const typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(const std::pair<_Tp1, _Tp2>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|229|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|note:   'std::tuple<float, int, char, placeholder<0, int> >' is not derived from 'const std::pair<_Tp1, _Tp2>'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|234|note: candidate: 'template<unsigned int _Int, class _Tp1, class _Tp2> constexpr const typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type&& std::get(const std::pair<_Tp1, _Tp2>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|234|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|note:   'std::tuple<float, int, char, placeholder<0, int> >' is not derived from 'const std::pair<_Tp1, _Tp2>'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|243|note: candidate: 'template<class _Tp, class _Up> constexpr _Tp& std::get(std::pair<_T1, _T2>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|243|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|248|note: candidate: 'template<class _Tp, class _Up> constexpr const _Tp& std::get(const std::pair<_T1, _T2>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|248|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|253|note: candidate: 'template<class _Tp, class _Up> constexpr _Tp&& std::get(std::pair<_T1, _T2>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|253|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|258|note: candidate: 'template<class _Tp, class _Up> constexpr const _Tp&& std::get(const std::pair<_T1, _T2>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|258|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|263|note: candidate: 'template<class _Tp, class _Up> constexpr _Tp& std::get(std::pair<_Up, _Tp>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|263|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|268|note: candidate: 'template<class _Tp, class _Up> constexpr const _Tp& std::get(const std::pair<_Up, _Tp>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|268|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|273|note: candidate: 'template<class _Tp, class _Up> constexpr _Tp&& std::get(std::pair<_Up, _Tp>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|273|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|278|note: candidate: 'template<class _Tp, class _Up> constexpr const _Tp&& std::get(const std::pair<_Up, _Tp>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|278|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\array|307|note: candidate: 'template<unsigned int _Int, class _Tp, unsigned int _Nm> constexpr _Tp& std::get(std::array<_Tp, _Nm>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\array|307|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|note:   'std::tuple<float, int, char, placeholder<0, int> >' is not derived from 'std::array<_Tp, _Nm>'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\array|316|note: candidate: 'template<unsigned int _Int, class _Tp, unsigned int _Nm> constexpr _Tp&& std::get(std::array<_Tp, _Nm>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\array|316|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|note:   'std::tuple<float, int, char, placeholder<0, int> >' is not derived from 'std::array<_Tp, _Nm>'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\array|324|note: candidate: 'template<unsigned int _Int, class _Tp, unsigned int _Nm> constexpr const _Tp& std::get(const std::array<_Tp, _Nm>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\array|324|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|note:   'std::tuple<float, int, char, placeholder<0, int> >' is not derived from 'const std::array<_Tp, _Nm>'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\array|333|note: candidate: 'template<unsigned int _Int, class _Tp, unsigned int _Nm> constexpr const _Tp&& std::get(const std::array<_Tp, _Nm>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\array|333|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|note:   'std::tuple<float, int, char, placeholder<0, int> >' is not derived from 'const std::array<_Tp, _Nm>'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1320|note: candidate: 'template<unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >& std::get(std::tuple<_Elements ...>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1320|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1326|note: candidate: 'template<unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >& std::get(const std::tuple<_Elements ...>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1326|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1332|note: candidate: 'template<unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >&& std::get(std::tuple<_Elements ...>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1332|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1341|note: candidate: 'template<unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >&& std::get(const std::tuple<_Elements ...>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1341|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1364|note: candidate: 'template<class _Tp, class ... _Types> constexpr _Tp& std::get(std::tuple<_Elements ...>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1364|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1370|note: candidate: 'template<class _Tp, class ... _Types> constexpr _Tp&& std::get(std::tuple<_Elements ...>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1370|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1376|note: candidate: 'template<class _Tp, class ... _Types> constexpr const _Tp& std::get(const std::tuple<_Elements ...>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1376|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1383|note: candidate: 'template<class _Tp, class ... _Types> constexpr const _Tp&& std::get(const std::tuple<_Elements ...>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1383|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|98|note: candidate: 'template<unsigned int I, unsigned int NB, class T, class ... D, class ... E, class ... F, class> static constexpr auto append_if<Pred, R>::f(T) [with unsigned int I = I; unsigned int NB = NB; T = T; D = {D ...}; E = {E ...}; F = {F ...}; <template-parameter-2-7> = <template-parameter-1-7>; Pred = is_placeholder; R = std::tuple]'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|98|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|error: no matching function for call to 'get<4>(std::tuple<float, int, char, placeholder<0, int> >)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|219|note: candidate: 'template<unsigned int _Int, class _Tp1, class _Tp2> constexpr typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(std::pair<_Tp1, _Tp2>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|219|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|note:   'std::tuple<float, int, char, placeholder<0, int> >' is not derived from 'std::pair<_Tp1, _Tp2>'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|224|note: candidate: 'template<unsigned int _Int, class _Tp1, class _Tp2> constexpr typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type&& std::get(std::pair<_Tp1, _Tp2>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|224|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|note:   'std::tuple<float, int, char, placeholder<0, int> >' is not derived from 'std::pair<_Tp1, _Tp2>'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|229|note: candidate: 'template<unsigned int _Int, class _Tp1, class _Tp2> constexpr const typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(const std::pair<_Tp1, _Tp2>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|229|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|note:   'std::tuple<float, int, char, placeholder<0, int> >' is not derived from 'const std::pair<_Tp1, _Tp2>'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|234|note: candidate: 'template<unsigned int _Int, class _Tp1, class _Tp2> constexpr const typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type&& std::get(const std::pair<_Tp1, _Tp2>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|234|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|note:   'std::tuple<float, int, char, placeholder<0, int> >' is not derived from 'const std::pair<_Tp1, _Tp2>'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|243|note: candidate: 'template<class _Tp, class _Up> constexpr _Tp& std::get(std::pair<_T1, _T2>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|243|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|248|note: candidate: 'template<class _Tp, class _Up> constexpr const _Tp& std::get(const std::pair<_T1, _T2>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|248|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|253|note: candidate: 'template<class _Tp, class _Up> constexpr _Tp&& std::get(std::pair<_T1, _T2>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|253|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|258|note: candidate: 'template<class _Tp, class _Up> constexpr const _Tp&& std::get(const std::pair<_T1, _T2>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|258|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|263|note: candidate: 'template<class _Tp, class _Up> constexpr _Tp& std::get(std::pair<_Up, _Tp>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|263|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|268|note: candidate: 'template<class _Tp, class _Up> constexpr const _Tp& std::get(const std::pair<_Up, _Tp>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|268|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|273|note: candidate: 'template<class _Tp, class _Up> constexpr _Tp&& std::get(std::pair<_Up, _Tp>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|273|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|278|note: candidate: 'template<class _Tp, class _Up> constexpr const _Tp&& std::get(const std::pair<_Up, _Tp>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\utility|278|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\array|307|note: candidate: 'template<unsigned int _Int, class _Tp, unsigned int _Nm> constexpr _Tp& std::get(std::array<_Tp, _Nm>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\array|307|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|note:   'std::tuple<float, int, char, placeholder<0, int> >' is not derived from 'std::array<_Tp, _Nm>'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\array|316|note: candidate: 'template<unsigned int _Int, class _Tp, unsigned int _Nm> constexpr _Tp&& std::get(std::array<_Tp, _Nm>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\array|316|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|note:   'std::tuple<float, int, char, placeholder<0, int> >' is not derived from 'std::array<_Tp, _Nm>'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\array|324|note: candidate: 'template<unsigned int _Int, class _Tp, unsigned int _Nm> constexpr const _Tp& std::get(const std::array<_Tp, _Nm>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\array|324|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|note:   'std::tuple<float, int, char, placeholder<0, int> >' is not derived from 'const std::array<_Tp, _Nm>'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\array|333|note: candidate: 'template<unsigned int _Int, class _Tp, unsigned int _Nm> constexpr const _Tp&& std::get(const std::array<_Tp, _Nm>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\array|333|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|76|note:   'std::tuple<float, int, char, placeholder<0, int> >' is not derived from 'const std::array<_Tp, _Nm>'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1320|note: candidate: 'template<unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >& std::get(std::tuple<_Elements ...>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1320|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1326|note: candidate: 'template<unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >& std::get(const std::tuple<_Elements ...>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1326|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1332|note: candidate: 'template<unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >&& std::get(std::tuple<_Elements ...>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1332|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1341|note: candidate: 'template<unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >&& std::get(const std::tuple<_Elements ...>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1341|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1364|note: candidate: 'template<class _Tp, class ... _Types> constexpr _Tp& std::get(std::tuple<_Elements ...>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1364|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1370|note: candidate: 'template<class _Tp, class ... _Types> constexpr _Tp&& std::get(std::tuple<_Elements ...>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1370|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1376|note: candidate: 'template<class _Tp, class ... _Types> constexpr const _Tp& std::get(const std::tuple<_Elements ...>&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1376|note:   template argument deduction/substitution failed:|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1383|note: candidate: 'template<class _Tp, class ... _Types> constexpr const _Tp&& std::get(const std::tuple<_Elements ...>&&)'|
                                C:\TDM-GCC-32\lib\gcc\mingw32\9.2.0\include\c++\tuple|1383|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|103|note: candidate: 'template<unsigned int I, unsigned int NB, class T, class ... D, class ... E, class ... F, class ... G, class> static constexpr auto append_if<Pred, R>::f(T) [with unsigned int I = I; unsigned int NB = NB; T = T; D = {D ...}; E = {E ...}; F = {F ...}; G = {G ...}; <template-parameter-2-8> = <template-parameter-1-8>; Pred = is_placeholder; R = std::tuple]'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|103|note:   substitution of deduced template arguments resulted in errors seen above|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|107|note: candidate: 'template<unsigned int I, unsigned int NB, class T, class ... D, class ... E, class ... F, class ... G, class ... H, class> static constexpr auto append_if<Pred, R>::f(T) [with unsigned int I = I; unsigned int NB = NB; T = T; D = {D ...}; E = {E ...}; F = {F ...}; G = {G ...}; H = {H ...}; <template-parameter-2-9> = <template-parameter-1-9>; Pred = is_placeholder; R = std::tuple]'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|107|note:   template argument deduction/substitution failed:|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|106|error: no type named 'type' in 'struct std::enable_if<false, void>'|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp||In function 'int main(int, char**)':|
                                C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|173|error: variable or field 't' declared void|
                                ||=== Build failed: 16 error(s), 38 warning(s) (0 minute(s), 3 second(s)) ===|
                                

                                Je pense pas que ça doit être possible de le faire, enfin si sûrement mais je vois pas du tout comment m'y prendre.



                                -
                                Edité par OmbreNoire 11 juin 2021 à 22:28:16

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  12 juin 2021 à 23:07:48

                                  Et voilà j'ai réussi, il y a l'instanciation de std::tuple mais, je ne suis pas fou au point de faire un fichier de plus de 13 000 lignes de code juste pour gagner quelques secondes en compilation, mais à mon avis ça ne résoudra pas le problème du plantage mais au moins ça va compiler sous visual studio parce que corriger toutes les erreurs du fichier mp.hpp.

                                  template <size_t I, typename T>
                                  struct placeholder {
                                      using type = T;
                                      static constexpr std::size_t index = I;
                                  };
                                  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<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);
                                      }
                                  };
                                  //Make index sequences from an offset.
                                  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;
                                  //Concatenate two sequences of indexes into one.
                                  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>
                                  //Return a tuple with elements at indexes.
                                  auto select_tuple(std::index_sequence<Ints...>)
                                  {
                                   T tuple;
                                   return std::make_tuple(
                                      std::get<Ints>(std::forward<T>(tuple))...);
                                  }
                                  //Remove the Nth elements of a tuple.
                                  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{});
                                  }
                                  //Remove every types, that are not satisfied a condition.
                                  template<template<class...> class Pred>
                                  struct append_if {
                                      //If the type statisfy the condition we don't remove it and return the tuple itself.
                                      template <size_t I, class B, class T, class = typename std::enable_if<B::value>::type>
                                      static constexpr auto get(T tp) {
                                          return tp;
                                      }
                                      //If the type doesn't satisfy the condition we remove it from the tuple and return the new tuple.
                                      //As a good surprise for me it works event if the type of the returned tuple is not the same as the type of the provided tuple.
                                      template <size_t I, class B, class T, class... D, class = typename std::enable_if<!B::value>::type>
                                      static constexpr auto get(T tp) {
                                          //std::cout<<"I : "<<I<<std::endl;
                                          return remove_Nth<I, T>();
                                      }
                                      //final case : we stop recursion when we have browsed all the elements of the tuple and we check if the last element must be removed.
                                      template <size_t I=0, size_t NB=0, class T, class = typename std::enable_if<(I-NB == std::tuple_size<T>()-1 && Pred<std::tuple_element_t<I-NB, T>>::value)>::type>
                                      static constexpr auto f(T tp) {
                                          return get<I-NB, std::true_type>(tp);
                                      }
                                      template <size_t I=0, size_t NB=0, class T, class... D, class = typename std::enable_if<(I-NB == std::tuple_size<T>()-1 && !Pred<std::tuple_element_t<I-NB, T>>::value)>::type>
                                      static constexpr auto f(T tp) {
                                          return get<I-NB, std::false_type>(tp);
                                      }
                                      template <size_t I=0, size_t NB=0, class T, class... D, class... E, class = typename std::enable_if<(I-NB < std::tuple_size<T>()-1  && Pred<std::tuple_element_t<I-NB, T>>::value)>::type>
                                      static constexpr auto f(T tp) {
                                          return f<I+1, NB>(get<I-NB, std::true_type>(tp));
                                      }
                                      template <size_t I=0, size_t NB=0, class T, class... D, class... E, class ... F, class = typename std::enable_if<(I-NB < std::tuple_size<T>()-1 && !Pred<std::tuple_element_t<I-NB, T>>::value)>::type>
                                      static constexpr auto f(T tp) {
                                          return f<I+1, NB+1>(get<I-NB, std::false_type>(tp));
                                      }
                                  };
                                  //Copy every tuple elements which satisfied a predicate.
                                  template<template <class...> class Pred, typename T>
                                  struct copy_if {
                                      using f = decltype(append_if<Pred>::template f(T()));
                                  };
                                  //Sort every elements of a tuple with the specified comparator.
                                  template <class Comp>
                                  struct swap_if {
                                      //Case 1 : If the next element is greater than the current element, no need to swap, we just return the tuple itself.
                                      template <size_t I, size_t J, class T, class = typename std::enable_if<Comp::template f<std::tuple_element_t<I, T>, std::tuple_element_t<J, T>>::value>::type>
                                      static constexpr auto get (T tp) {
                                         return T();
                                      }
                                      //Case 2 : If the new element is smaller than the current element, we swap the tuple's elements.
                                      template <size_t I, size_t J, class T, class... D, class = typename std::enable_if<!Comp::template f<std::tuple_element_t<I, T>, std::tuple_element_t<J, T>>::value>::type>
                                      static constexpr auto get (T tp) {
                                         using first = std::make_index_sequence<I>;
                                         using second = std::index_sequence<J>;
                                         using third = offset_sequence_t<I+1,std::make_index_sequence<J-I-1>>;
                                         using four = std::index_sequence<I>;
                                         using last = offset_sequence_t<J+1,std::make_index_sequence<std::tuple_size<T>()-J-1>>;
                                         using indices = cat_sequence_t<first, cat_sequence_t<second, cat_sequence_t<third, cat_sequence_t<four, last>>>>;
                                         return select_tuple<T>(indices{});
                                      }
                                      //final case second recursions, we
                                      template <size_t I, size_t J, class T, class = typename std::enable_if<(J == std::tuple_size<T>()-1)>::type>
                                      static constexpr auto f2(T tp) {
                                          return get<I, J>(tp);
                                      }
                                      //General case second recursion, we check if we need to swap the tuple's elements for next elements.
                                      template <size_t I, size_t J, class T, class... D, class = typename std::enable_if<(J < std::tuple_size<T>()-1)>::type>
                                      static constexpr auto f2(T tp) {
                                          return f2<I, J+1>(get<I, J>(tp));
                                      }
                                      //final case, we stop the recursion and we check if the penultimate element and the last element need to be swapped.
                                      template <size_t I=0, class T, class = typename std::enable_if<(I == std::tuple_size<T>() - 2)>::type>
                                      static constexpr auto f(T tp) {
                                          return f2<I, I+1>(tp);
                                      }
                                      //General case : do recursion to check if tuple's elements need to be swapped.
                                      template <size_t I=0, class T, class... D, class = typename std::enable_if<(I < std::tuple_size<T>() - 2)>::type>
                                      static constexpr auto f(T tp) {
                                          return f<I+1>(f2<I, I+1>(tp));
                                      }
                                  };
                                  template <class Comp, typename T>
                                  struct sort {
                                      using f = decltype(swap_if<Comp>::template f(T()));
                                  };
                                  struct make_unique {
                                      template <size_t I, size_t J, class B, class T, class = typename std::enable_if<B::value>::type>
                                      static constexpr auto get(T tp) {
                                          return remove_Nth<I, T>();
                                      }
                                      template <size_t I, size_t J, class B, class T, class... D, class = typename std::enable_if<!B::value>::type>
                                      static constexpr auto get(T tp) {
                                          return tp;
                                      }
                                      //final case second recursions, we
                                      template <size_t I, size_t J, size_t NB, class T, class = typename std::enable_if<(J-NB == std::tuple_size<T>()-1 && std::is_same<std::tuple_element_t<I, T>, std::tuple_element_t<J, T>>::value)>::type>
                                      static constexpr auto f2(T tp) {
                                          return get<I-NB, J-NB, std::true_type>(tp);
                                      }
                                      template <size_t I, size_t J, size_t NB, class T, class... D, class = typename std::enable_if<(J-NB == std::tuple_size<T>()-1 && !std::is_same<std::tuple_element_t<I, T>, std::tuple_element_t<J, T>>::value)>::type>
                                      static constexpr auto f2(T tp) {
                                          return get<I-NB, J-NB, std::false_type>(tp);
                                      }
                                      //General case second recursion, we check if we need to swap the tuple's elements for next elements.
                                      template <size_t I, size_t J, size_t NB, class T, class... D, class... E, class = typename std::enable_if<(J-NB < std::tuple_size<T>()-1 && std::is_same<std::tuple_element_t<I, T>, std::tuple_element_t<J, T>>::value)>::type>
                                      static constexpr auto f2(T tp) {
                                          return f2<I, J+1, NB+1>(get<I-NB, J-NB, std::true_type>(tp));
                                      }
                                      template <size_t I, size_t J, size_t NB, class T, class... D, class... E, class... F, class = typename std::enable_if<(J-NB < std::tuple_size<T>()-1 && !std::is_same<std::tuple_element_t<I, T>, std::tuple_element_t<J, T>>::value)>::type>
                                      static constexpr auto f2(T tp) {
                                          return f2<I, J+1, NB>(get<I-NB, J-NB, std::false_type>(tp));
                                      }
                                      //final case, we stop the recursion and we check if the penultimate element and the last element need to be swapped.
                                      template <size_t I=0, class T, class = typename std::enable_if<(I == std::tuple_size<T>() - 2)>::type>
                                      static constexpr auto f(T tp) {
                                          return f2<I, I+1, 0>(tp);
                                      }
                                      //General case : do recursion to check if tuple's elements need to be swapped.
                                      template <size_t I=0, class T, class... D, class = typename std::enable_if<(I < std::tuple_size<T>() - 2)>::type>
                                      static constexpr auto f(T tp) {
                                          return f<I+1>(f2<I, I+1, 0>(tp));
                                      }
                                  };
                                  template <class T>
                                  struct unique {
                                      using f = decltype(make_unique::f(T()));
                                  };
                                  template <class T, template<class...> class R, class Seq>
                                  struct lift {
                                  };
                                  template <class T, template<class...> class R, size_t... Ints>
                                  struct lift <T, R, std::index_sequence<Ints...>> {
                                      using f = R<std::tuple_element_t<Ints, T>...>;
                                  };
                                  int main(int argc, char* argv[])
                                  {
                                      using tuple_t = sort<LessPlaceceholder, unique<copy_if<is_placeholder,std::tuple<placeholder<0, int>, placeholder<3, int>, float, placeholder<2, int>, int, placeholder<1, int>, char, placeholder<0, int>>>::f>::f>::f;
                                      using late_params_t = lift<tuple_t, LateParameters,std::make_index_sequence<std::tuple_size<tuple_t>()-0>>::f;
                                      return 0;
                                  }

                                  Reste plus qu'à tester, pour voir si le plantage vient du fichier mp.hpp ou du compilateur mais au moins je pourrai tester avec un autre compilateur pour voir si le crash persiste parce que c'est quand même curieux que ici le calcul sur sizeof ne soit pas bon et que la valeur du pointeur sur l'objet dans le tuple change parfois de valeur toute seule :

                                  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),
                                                0
                                              };

                                  Faudrait que je test sans les appels aux fonctions de la librairie mp pour voir.

                                  Mais au moins je pourrai tester avec d'autres compilateurs parce que le fichier mp.hpp ne compile pas sous visual studio, celui-ci va compiler et il y a trop d'erreurs dans le fichier mp.hpp pour que je puisse les corriger :

                                  template <size_t I, typename T>
                                  struct placeholder {
                                      using type = T;
                                      static constexpr std::size_t index = I;
                                  };
                                  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<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);
                                      }
                                  };
                                  //Make index sequences from an offset.
                                  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;
                                  //Concatenate two sequences of indexes into one.
                                  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>
                                  //Return a tuple with elements at indexes.
                                  auto select_tuple(std::index_sequence<Ints...>)
                                  {
                                   T tuple;
                                   return std::make_tuple(
                                      std::get<Ints>(std::forward<T>(tuple))...);
                                  }
                                  //Remove the Nth elements of a tuple.
                                  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{});
                                  }
                                  //Remove every types, that are not satisfied a condition.
                                  template<template<class...> class Pred>
                                  struct append_if {
                                      //If the type statisfy the condition we don't remove it and return the tuple itself.
                                      template <size_t I, class B, class T, class = typename std::enable_if<B::value>::type>
                                      static constexpr auto get(T tp) {
                                          return tp;
                                      }
                                      //If the type doesn't satisfy the condition we remove it from the tuple and return the new tuple.
                                      //As a good surprise for me it works event if the type of the returned tuple is not the same as the type of the provided tuple.
                                      template <size_t I, class B, class T, class... D, class = typename std::enable_if<!B::value>::type>
                                      static constexpr auto get(T tp) {
                                          //std::cout<<"I : "<<I<<std::endl;
                                          return remove_Nth<I, T>();
                                      }
                                      //final case : we stop recursion when we have browsed all the elements of the tuple and we check if the last element must be removed.
                                      template <size_t I=0, size_t NB=0, class T, class = typename std::enable_if<(I-NB == std::tuple_size<T>()-1 && Pred<std::tuple_element_t<I-NB, T>>::value)>::type>
                                      static constexpr auto f(T tp) {
                                          return get<I-NB, std::true_type>(tp);
                                      }
                                      template <size_t I=0, size_t NB=0, class T, class... D, class = typename std::enable_if<(I-NB == std::tuple_size<T>()-1 && !Pred<std::tuple_element_t<I-NB, T>>::value)>::type>
                                      static constexpr auto f(T tp) {
                                          return get<I-NB, std::false_type>(tp);
                                      }
                                      template <size_t I=0, size_t NB=0, class T, class... D, class... E, class = typename std::enable_if<(I-NB < std::tuple_size<T>()-1  && Pred<std::tuple_element_t<I-NB, T>>::value)>::type>
                                      static constexpr auto f(T tp) {
                                          return f<I+1, NB>(get<I-NB, std::true_type>(tp));
                                      }
                                      template <size_t I=0, size_t NB=0, class T, class... D, class... E, class ... F, class = typename std::enable_if<(I-NB < std::tuple_size<T>()-1 && !Pred<std::tuple_element_t<I-NB, T>>::value)>::type>
                                      static constexpr auto f(T tp) {
                                          return f<I+1, NB+1>(get<I-NB, std::false_type>(tp));
                                      }
                                  };
                                  //Copy every tuple elements which satisfied a predicate.
                                  template<template <class...> class Pred, typename T>
                                  struct copy_if {
                                      using f = decltype(append_if<Pred>::template f(T()));
                                  };
                                  //Sort every elements of a tuple with the specified comparator.
                                  template <class Comp>
                                  struct swap_if {
                                      //Case 1 : If the next element is greater than the current element, no need to swap, we just return the tuple itself.
                                      template <size_t I, size_t J, class T, class = typename std::enable_if<Comp::template f<std::tuple_element_t<I, T>, std::tuple_element_t<J, T>>::value>::type>
                                      static constexpr auto get (T tp) {
                                         return T();
                                      }
                                      //Case 2 : If the new element is smaller than the current element, we swap the tuple's elements.
                                      template <size_t I, size_t J, class T, class... D, class = typename std::enable_if<!Comp::template f<std::tuple_element_t<I, T>, std::tuple_element_t<J, T>>::value>::type>
                                      static constexpr auto get (T tp) {
                                         using first = std::make_index_sequence<I>;
                                         using second = std::index_sequence<J>;
                                         using third = offset_sequence_t<I+1,std::make_index_sequence<J-I-1>>;
                                         using four = std::index_sequence<I>;
                                         using last = offset_sequence_t<J+1,std::make_index_sequence<std::tuple_size<T>()-J-1>>;
                                         using indices = cat_sequence_t<first, cat_sequence_t<second, cat_sequence_t<third, cat_sequence_t<four, last>>>>;
                                         return select_tuple<T>(indices{});
                                      }
                                      //final case second recursions, we
                                      template <size_t I, size_t J, class T, class = typename std::enable_if<(J == std::tuple_size<T>()-1)>::type>
                                      static constexpr auto f2(T tp) {
                                          return get<I, J>(tp);
                                      }
                                      //General case second recursion, we check if we need to swap the tuple's elements for next elements.
                                      template <size_t I, size_t J, class T, class... D, class = typename std::enable_if<(J < std::tuple_size<T>()-1)>::type>
                                      static constexpr auto f2(T tp) {
                                          return f2<I, J+1>(get<I, J>(tp));
                                      }
                                      //final case, we stop the recursion and we check if the penultimate element and the last element need to be swapped.
                                      template <size_t I=0, class T, class = typename std::enable_if<(I == std::tuple_size<T>() - 2)>::type>
                                      static constexpr auto f(T tp) {
                                          return f2<I, I+1>(tp);
                                      }
                                      //General case : do recursion to check if tuple's elements need to be swapped.
                                      template <size_t I=0, class T, class... D, class = typename std::enable_if<(I < std::tuple_size<T>() - 2)>::type>
                                      static constexpr auto f(T tp) {
                                          return f<I+1>(f2<I, I+1>(tp));
                                      }
                                  };
                                  template <class Comp, typename T>
                                  struct sort {
                                      using f = decltype(swap_if<Comp>::template f(T()));
                                  };
                                  struct make_unique {
                                      template <size_t I, size_t J, class B, class T, class = typename std::enable_if<B::value>::type>
                                      static constexpr auto get(T tp) {
                                          return remove_Nth<I, T>();
                                      }
                                      template <size_t I, size_t J, class B, class T, class... D, class = typename std::enable_if<!B::value>::type>
                                      static constexpr auto get(T tp) {
                                          return tp;
                                      }
                                      //final case second recursions, we
                                      template <size_t I, size_t J, size_t NB, class T, class = typename std::enable_if<(J-NB == std::tuple_size<T>()-1 && std::is_same<std::tuple_element_t<I, T>, std::tuple_element_t<J, T>>::value)>::type>
                                      static constexpr auto f2(T tp) {
                                          return get<I-NB, J-NB, std::true_type>(tp);
                                      }
                                      template <size_t I, size_t J, size_t NB, class T, class... D, class = typename std::enable_if<(J-NB == std::tuple_size<T>()-1 && !std::is_same<std::tuple_element_t<I, T>, std::tuple_element_t<J, T>>::value)>::type>
                                      static constexpr auto f2(T tp) {
                                          return get<I-NB, J-NB, std::false_type>(tp);
                                      }
                                      //General case second recursion, we check if we need to swap the tuple's elements for next elements.
                                      template <size_t I, size_t J, size_t NB, class T, class... D, class... E, class = typename std::enable_if<(J-NB < std::tuple_size<T>()-1 && std::is_same<std::tuple_element_t<I, T>, std::tuple_element_t<J, T>>::value)>::type>
                                      static constexpr auto f2(T tp) {
                                          return f2<I, J+1, NB+1>(get<I-NB, J-NB, std::true_type>(tp));
                                      }
                                      template <size_t I, size_t J, size_t NB, class T, class... D, class... E, class... F, class = typename std::enable_if<(J-NB < std::tuple_size<T>()-1 && !std::is_same<std::tuple_element_t<I, T>, std::tuple_element_t<J, T>>::value)>::type>
                                      static constexpr auto f2(T tp) {
                                          return f2<I, J+1, NB>(get<I-NB, J-NB, std::false_type>(tp));
                                      }
                                      //final case, we stop the recursion and we check if the penultimate element and the last element need to be swapped.
                                      template <size_t I=0, class T, class = typename std::enable_if<(I == std::tuple_size<T>() - 2)>::type>
                                      static constexpr auto f(T tp) {
                                          return f2<I, I+1, 0>(tp);
                                      }
                                      //General case : do recursion to check if tuple's elements need to be swapped.
                                      template <size_t I=0, class T, class... D, class = typename std::enable_if<(I < std::tuple_size<T>() - 2)>::type>
                                      static constexpr auto f(T tp) {
                                          return f<I+1>(f2<I, I+1, 0>(tp));
                                      }
                                  };
                                  template <class T>
                                  struct unique {
                                      using f = decltype(make_unique::f(T()));
                                  };
                                  template <class T, template<class...> class R, class Seq>
                                  struct lift {
                                  };
                                  template <class T, template<class...> class R, size_t... Ints>
                                  struct lift <T, R, std::index_sequence<Ints...>> {
                                      using f = R<std::tuple_element_t<Ints, T>...>;
                                  };
                                  int main(int argc, char* argv[])
                                  {
                                      using tuple_t = sort<LessPlaceceholder, unique<copy_if<is_placeholder,std::tuple<placeholder<0, int>, placeholder<3, int>, float, placeholder<2, int>, int, placeholder<1, int>, char, placeholder<0, int>>>::f>::f>::f;
                                      using late_params_t = lift<tuple_t, LateParameters,std::make_index_sequence<std::tuple_size<tuple_t>()-0>>::f;
                                      return 0;
                                  }






                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    19 juin 2021 à 11:52:09

                                    Finalement, j'ai fini par réussir!!! 

                                    J'ai retiré les macros qui m'obligeaient à définir un nombre maximum de placeholders supportés et faire une récursion dégueulasse parce que ça m'ennuyait vraiment et je ne trouvais pas ça propre du tout, grâce au fichier mp.hpp j'ai réussi à le faire, j'ai recherché pendant longtemps une lib de ce genre mais je n'en trouvais pas, je dirais juste un grand merci à Jonathan!!!

                                    Par contre j'ai laissé l'héritage parce que je n'aime pas utiliser des void* qui sont souvent la cause de plantages comme ça a été le cas avec le code source proposé par Jonathan, le seul endroit ou j'utilise un void* c'est pour passer les arguments pour les placeholders parce que là je n'ai pas le choix parce qu'avec les fonctions virtuelles je ne peux pas utiliser de template.

                                    Mais au moins, ça ne plante plus!!!

                                    Voici donc la version finale de la classe FastDelegate. (et je ne la changerai plus!)

                                    /**
                                      *\namespace odfaeg
                                      * the namespace of the Opensource Development Framework Adapted for Every Games.
                                      */
                                    namespace odfaeg {
                                        namespace core {
                                            /**
                                            *  \file  fastDelegate.h
                                            *  \class IRefVal
                                            *  \brief Interface for the warppers to references, values and pointers.
                                            *  This class is used store references, pointers and values to pass to the callack's functions.
                                            *  \param T : the type of the value to wrap.
                                            *  \author Duroisin.L
                                            *  \version 1.0
                                            *  \date 1/02/2014
                                            */
                                            template<std::size_t i, class T>
                                            struct Parameter
                                            {
                                              T value;
                                            };
                                            template<class... Placeholders>
                                            struct LateParameters : Parameter<Placeholders::index, typename Placeholders::type>... {
                                    
                                            };
                                            template<class T, class LateParamsT>
                                            struct IRefVal {
                                                /**\fn
                                                *  \brief default constructor
                                                */
                                                IRefVal()=default;
                                                /**\fn T& get()
                                                *  \brief get the reference of the wrapped type.
                                                *  \return the reference of the wrapped type.
                                                */
                                                virtual T& bind(void* params) = 0;
                                                virtual T& get(void* params) = 0;
                                                /**\fn std::unique_ptr<IRefVal<T>> clone() const = 0;
                                                *  \brief copy the wrapper.
                                                *  \return the copied wrapper.*/
                                                virtual std::unique_ptr<IRefVal<T, LateParamsT>> clone() const = 0;
                                                /**\fn destructor*/
                                                virtual ~IRefVal(){}
                                    
                                            protected:
                                                /**\fn IRefVal(const IRefVal&)
                                                *  \brief constructor, pass the reference to wrap.
                                                *  \param const IRefVal& : the reference to wrap.
                                                */
                                                IRefVal(const IRefVal&){}
                                                /** \fn IRefVal& operator=(const IRefVal&)
                                                *   \brief affector.
                                                *   \param const IRefVal& : the wrapper to affect.
                                                *   \return the affected wrapper.*/
                                                IRefVal& operator=(const IRefVal&)
                                                { return *this; }
                                            };
                                            /**
                                            *  \file  fastDelegate.h
                                            *  \class Ref
                                            *  \brief Warp a reference. (Use std::reference_wrapper so we can pass a reference with std::ref)
                                            *  \author Duroisin.L
                                            *  \version 1.0
                                            *  \date 1/02/2014
                                            */
                                            template <typename T, typename LateParamsT>
                                            class RefVal;
                                            template<class T, typename LateParamsT>
                                            struct Ref : IRefVal<T, LateParamsT> {
                                                /**
                                                *\fn Ref(const std::reference_wrapper<T>& r)
                                                *\brief Constructor : pass an std::reference_wrapper to the wrapper.
                                                *\param std::reference_wrapper<T>& r : the reference_wrapper.
                                                */
                                                Ref(const std::reference_wrapper<T>& r)
                                                    : ref(r)
                                                {}
                                                /**
                                                * \fn T& get()
                                                * \brief return a reference to an object.
                                                * \return T& the reference to the object.
                                                */
                                                T& bind(void* params) {
                                                  return ref.get();
                                                }
                                                T& get(void* params)
                                                { return ref.get(); }
                                                /**
                                                * \fn std::unique_ptr<IRefVal<T>> clone() const
                                                * \brief copy the reference wrapper.
                                                * \return std::unique_ptr<IRefVal<T>> : the cloned wrapper.
                                                */
                                                std::unique_ptr<IRefVal<T, LateParamsT>> clone() const
                                                { return std::make_unique<Ref>(*this); }
                                            private:
                                                std::reference_wrapper<T> ref; /**> the std::reference_wrapper which warp the reference.*/
                                            };
                                            /**
                                            *  \file  fastDelegate.h
                                            *  \class Val
                                            *  \brief Warp a value.
                                            *  \author Duroisin.L
                                            *  \version 1.0
                                            *  \date 1/02/2014
                                            */
                                            template<class T, class LateParamsT>
                                            struct Val : IRefVal<T, LateParamsT> {
                                                /**\fn Val(const T& t)
                                                *  \brief pass a value to the wrapper.
                                                *  \param const T& t : the value to pass.
                                                */
                                                Val(const T& t)
                                                    : val(t)
                                                {}
                                                /** \fn
                                                *   \brief return the value
                                                *   \return T& : return the value.
                                                */
                                                T& bind(void* params) {
                                                  return val;
                                                }
                                                T& get(void* params)
                                                { return val; }
                                                /**
                                                * \fn std::unique_ptr<IRefVal<T>> clone() const
                                                * \brief copy the value wrapper.
                                                * \return std::unique_ptr<IRefVal<T>> : the cloned wrapper.
                                                */
                                                std::unique_ptr<IRefVal<T, LateParamsT>> clone() const
                                                { return std::make_unique<Val>(*this); }
                                            private:
                                                T val; /**> T val : keep the value of the wrapper.*/
                                            };
                                            template<size_t I, class T>
                                            struct ph
                                            {
                                                using type = T;
                                                static constexpr std::size_t index = I;
                                            };
                                            template<class T>
                                            struct is_placeholder
                                            : std::false_type
                                            {};
                                            template<std::size_t I, class T>
                                            struct is_placeholder<ph<I, T>>
                                            : std::true_type
                                            {};
                                            struct LessPlaceceholder
                                            {
                                              template<class PlaceHolder1, class PlaceHolder2>
                                              using f = std::bool_constant<PlaceHolder1::index < PlaceHolder2::index>;
                                            };
                                            template<size_t I, class T, class LateParamsT>
                                            struct placeholder : IRefVal<T, LateParamsT>
                                            {
                                                std::unique_ptr<IRefVal<T, LateParamsT>> clone() const
                                                { return std::make_unique<placeholder>(*this); }
                                                T& bind(void* params) {
                                                    LateParamsT& paramsT = *static_cast<LateParamsT*>(params);
                                                    return static_cast<Parameter<I, T>&>(paramsT).value;
                                                }
                                                T& get(void* params)
                                                {
                                                    LateParamsT& paramsT = *static_cast<LateParamsT*>(params);
                                                    return static_cast<Parameter<I, T>&>(paramsT).value;
                                                }
                                                using type = T;
                                                static constexpr std::size_t index = I;
                                            };
                                            /**
                                            *  \file  fastDelegate.h
                                            *  \class Ref
                                            *  \brief Warp a pointer.
                                            *  \author Duroisin.L
                                            *  \version 1.0
                                            *  \date 1/02/2014
                                            */
                                            /**
                                            *  \file  fastDelegate.h
                                            *  \class RefVal
                                            *  \brief Wrap a pointer, a value or a reference and keep a pointer to the generic wrapper.
                                            *  Call the right constructor depending on the wrapper's or value's type.
                                            *  \author Duroisin.L
                                            *  \version 1.0
                                            *  \date 1/02/2014
                                            */
                                            template<class T, class LateParamsT>
                                            struct RefVal {
                                                /**
                                                * \fn RefVal (const T& t)
                                                * \brief constructor : construct a wrapper to a value
                                                * \param const T& t : the value to
                                                */
                                                RefVal(const T& t)
                                                : rv(std::make_unique<Val<T, LateParamsT>>(t))
                                                {}
                                                /**
                                                * \fn RefVal (const std::reference_wrapper<T>& r)
                                                * \brief constructor : construct a wrapper to an std::reference_wrapper.
                                                * \param const std::reference_wrapper<T>& : the std::reference_wrapper to pass.
                                                */
                                                RefVal(const std::reference_wrapper<T>& r)
                                                : rv(std::make_unique<Ref<T, LateParamsT>>(r))
                                                {}
                                                /** \fn RefVal (const RefVal& rhs)
                                                *   \brief copy constructor, copy the wrapper with the right wrapper type.
                                                *   \param const RefVal& rhs : the wrapper to copy.
                                                */
                                                template<size_t I>
                                                RefVal(ph<I,T>&&)
                                                    : rv(std::make_unique<placeholder<I,T,LateParamsT>>())
                                                {}
                                                RefVal(const RefVal& rhs)
                                                {
                                                    rv = rhs.rv->clone();
                                                }
                                                /** \fn RefVal& operator= (const RefVal& rhs)
                                                *   \brief affector.
                                                *   \param const RefVal& rhs : the wrapper to affect.
                                                */
                                                RefVal& operator=(const RefVal& rhs)
                                                { rv=rhs.rv->clone(); return *this; }
                                                /** \fn T& get() const
                                                *   \brief get the wrapper.
                                                *   \return a unique pointer to the generic wrapper interface.
                                                */
                                                T& bind(void* params) {
                                                    return rv->bind(params);
                                                }
                                                T& get(void* params) const
                                                { return rv->get(params); }
                                            private:
                                                std::unique_ptr<IRefVal<T, LateParamsT>> rv; /**> a pointer to the generic wrapper interface.*/
                                            };
                                            //Classe de trait pour déterminer le type à stocker
                                    
                                            //(Interne) Cas général
                                            /**
                                            *  \file  fastDelegate.h
                                            *  \class ToStoreImpl
                                            *  \param T the type of the wrapper.
                                            *  \brief Trait class which use an alias on a wrapped type.
                                            *  \author Duroisin.L
                                            *  \version 1.0
                                            *  \date 1/02/2014
                                            */
                                            template<class T>
                                            struct 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<ph<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 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, ph<I, U>>
                                            {
                                              using type = ph<I, U>;
                                            };
                                    
                                            template<class T>
                                            using ArgType_t = typename ArgType<T, std::remove_cv_t<T>>::type;
                                            /**
                                            *  \file  fastDelegate.h
                                            *  \class DynamicWrapper
                                            *  \param R the return type of the wrapped functor.
                                            *  \param C the class type of the wrapped functor.
                                            *  \param ArgT the arguments types of the wrapped functor.
                                            *  \brief This class warp a function pointer to a member function.
                                            *  I don't use an std::function directly here to keep the class type of the member function pointer
                                            *  because if the passed object is polymorphic, I need to apply a dynamic cast
                                            *  before calling the member function pointer on the object.
                                            *  \author Duroisin.L
                                            *  \version 1.0
                                            *  \date 1/02/2014
                                            */
                                            template<class R, class C, class... ArgT>
                                            struct DynamicWrapper {
                                                /**\fn DynamicWrapper(R(C::*pf)(ArgT...)) : pfunc(pf)
                                                *  \brief warp a pointer to a member function.
                                                *  \param R(C::*pf)(ArgT...) : the pointer to the member function.
                                                */
                                                DynamicWrapper(R(C::*pf)(ArgT...)) : pfunc(pf){}
                                                /**\fn R operator()(O* o, ArgU&&... arg) const
                                                *  \brief call the member function's pointer witht he given object and the given argument
                                                *  apply a dynamic_cast in case of the type of the object and the type of the classe containing the member function
                                                *  are not the same. (If the object is polymoprhic)
                                                *  If the cast fails it means that the object is not polymorphic so it throws an error.
                                                *  \param O* o : the object onwich to call the member function's pointer.
                                                *  \param ArgU&& arg : the arguments of the member function's pointer to call.
                                                */
                                                template<class O, class... ArgU>
                                                R operator()(O* o, ArgU&&... arg) const
                                                {
                                                    //std::cout<<"class : "<<typeid(C).name()<<std::endl<<"object derived : "<<typeid(o).name()<<std::endl<<"address : "<<o<<std::endl;
                                                    if(dynamic_cast<C*>(o))
                                                        return (dynamic_cast<C*>(o)->*pfunc)(std::forward<ArgU>(arg)...);
                                                    throw Erreur(0, "Invalid cast : types are nor polymorphic!", 1);
                                                }
                                            private:
                                                R (C::*pfunc)(ArgT...); /**> a pointer to a member's function.*/
                                            };
                                            /**
                                            *  \file  fastDelegate.h
                                            *  \class DynamicFunction
                                            *  \param F the type of the function.
                                            *  \brief Generic class for every functors type.
                                            *  \author Duroisin.L
                                            *  \version 1.0
                                            *  \date 1/02/2014
                                            */
                                            template<class F>
                                            class DynamicFunction;
                                            /**
                                            *  \file  fastDelegate.h
                                            *  \class DynamicFunction
                                            *  \param R the return type of the function.
                                            *  \param ArgT... the type of the arguments of the function.
                                            *  \brief Specialized template class for functors. (inherit from std::function)
                                            *  build a functor with the right constructor depending a the pointer's function type.
                                            *  \author Duroisin.L
                                            *  \version 1.0
                                            *  \date 1/02/2014
                                            */
                                            template<class R, class... ArgT>
                                            class DynamicFunction<R(ArgT...)>
                                                : std::function<R(ArgT...)>
                                            {
                                                /**> just an alias to the type of the base class.*/
                                                using Base = std::function<R(ArgT...)>;
                                    
                                            public:
                                                /**
                                                * \fn DynamicFunction(F&& f)
                                                * \brief pass a functor to the std::function.
                                                * \param F&& f : the functor to pass to the std::function.
                                                */
                                                template<class F>
                                                DynamicFunction(F&& f) : Base(std::forward<F>(f))
                                                {}
                                                /** \fn DynamicFunction (R (C::*pf)(ArgU...))
                                                *   \brief pass a pointer to a member's function to the DynamicWrapper, and then
                                                *   pass this wrapper to the std::function, so, the std::function call the operator() of the DynamicWrapper class
                                                *   and not the operator() of the std::function class so we can perform the dynamic_cast if necessary.
                                                *   \param R(C::*pf)(ArgU...) : the pointer to the member's function.
                                                *   \
                                                */
                                                template<class C, class... ArgU>
                                                DynamicFunction(R(C::*pf)(ArgU...))
                                                    : Base(DynamicWrapper<R,C,ArgU...>(pf))
                                                {}
                                                /**> just an allias to the operator() of the base class.*/
                                                using Base::operator();
                                            };
                                            /**
                                            *  \file  fastDelegate.h
                                            *  \class Delegate
                                            *  \param R the return type of the function.
                                            *  \brief Interface with can hold a delegate to every delegates types.
                                            *  \author Duroisin.L
                                            *  \version 1.0
                                            *  \date 1/02/2014
                                            */
                                            template<class R>
                                            struct Delegate {
                                                /**\fn Delegate()
                                                *  \brief default constructor.
                                                */
                                                Delegate() =default;
                                                /**\fn virtual std::unique_ptr<Delegate> clone() const = 0;
                                                *  \brief pure virtual function to redefine in the subclass to copy the delegate.
                                                *  \return std::unique_ptr<Delegate> a pointer to the copied delegate.
                                                */
                                                virtual std::unique_ptr<Delegate> clone() const = 0;
                                                /**\fn R operator()() = 0;
                                                *  \brief pure virtual function to redefines to call the std::function of the delegate.
                                                *  \return R : return the value returned by the std::function.
                                                */
                                                virtual void bind(void* params) = 0;
                                                virtual R operator()(void* params) = 0;
                                                /** /fn virtual Delegate()
                                                * \brief destructor
                                                */
                                                virtual ~Delegate(){}
                                    
                                            protected:
                                                /**
                                                * \fn Delegate (const Delegate&) {}
                                                * \brief copy constructor.
                                                * \param const Delegate& : the delegate to copy.
                                                */
                                                Delegate(const Delegate&){}
                                                /**
                                                * \fn Delegate& operator= (const Delegate&) {}
                                                * \brief affector.
                                                * \return Delegate& : return a reference to the current delegate.
                                                */
                                                Delegate& operator=(const Delegate&)
                                                {
                                                    return *this;
                                                }
                                            };
                                            /**
                                            *  \file  fastDelegate.h
                                            *  \class FastDelegateImpl
                                            *  \brief Implementation of the delegate's interfaces.
                                            *  \author Duroisin.L
                                            *  \version 1.0
                                            *  \date 1/02/2014
                                            */
                                            template<class R, class... ArgT>
                                            struct FastDelegateImpl : Delegate<R> {
                                                /** \fn FastDelegateImpl(F&& f, ArgU&&... arg)
                                                *   \brief constructor : create the delegate with the functor and the arguments value passed.
                                                */
                                                template<class F, class... ArgU>
                                                FastDelegateImpl(F&& f, ArgU&&... arg)
                                                    : func(std::forward<F>(f))
                                                    , param(std::forward<ArgU>(arg)...)
                                                    , tmpParam(std::forward<ArgU>(arg)...)
                                                {}
                                                /** \fn std::unique_ptr<Delegate<R>> clone() const
                                                *   \brief make a copy of the delegate.
                                                *   \return the copied delegate.
                                                */
                                                std::unique_ptr<Delegate<R>> clone() const
                                                { return std::make_unique<FastDelegateImpl>(*this); }
                                                /** \fn R operator()()
                                                *   \brief call the std::function of the delegate.
                                                *   \return the value returned by the std::function.
                                                */
                                                void bind(void* params) {
                                                  param = tmpParam;
                                                  bindParams(params);
                                                }
                                                R operator()(void* params)
                                                { return call(std::make_index_sequence<sizeof...(ArgT)>(), params); }
                                                /** \fn R operator()()
                                                *   \brief changed the parameter's values of the std::function.
                                                *   \param ArgU&&... args : the values for the parameters to the delegate's function.
                                                */
                                                template<class... ArgU>
                                                void setParams(ArgU&&... arg)
                                                {
                                                    param=std::make_tuple(std::forward<ArgU>(arg)...);
                                                    tmpParam=std::make_tuple(std::forward<ArgU>(arg)...);
                                                }
                                    
                                            private:
                                                /** \fn R call(std::index_sequence<I...>)
                                                *   \brief pass each elements of the tuple to the std::function and unwarp them.
                                                *   \param std::index_sequence<I...> : a sequence of indexes to get every elements of the tuple.
                                                *   \return the value returned by the std::function.
                                                */
                                                template <std::size_t I = 0>
                                                typename std::enable_if<I == sizeof...(ArgT)>::type
                                                bindParams(void* params) {
                                    
                                                }
                                                template <std::size_t I = 0>
                                                typename std::enable_if<(I < sizeof...(ArgT))>::type
                                                bindParams(void* params) {
                                                    std::get<I>(param) = std::get<I>(param).bind(params);
                                                    bindParams<I+1>(params);
                                                }
                                                template<std::size_t... I>
                                                R call(std::index_sequence<I...>, void* params) const
                                                {
                                                    return func(std::get<I>(param).get(params)...);
                                                }
                                                DynamicFunction<R(ToStore_t<ArgT>&...)> func; /**> a functor whith hold the pointer to a callback function.*/
                                                using late_params_t
                                                  = jln::mp::copy_if<jln::mp::lift<is_placeholder>,
                                                                jln::mp::unique<jln::mp::sort<LessPlaceceholder,
                                                                                    jln::mp::lift<LateParameters>>>>
                                                    ::f<std::remove_cv_t<ArgT>...>;
                                                std::tuple<RefVal<ToStore_t<ArgT>, late_params_t>...> param; /**> the wrapped values of the parameters to pass to the callback's function.*/
                                                std::tuple<RefVal<ToStore_t<ArgT>, late_params_t>...> tmpParam;
                                            };
                                            /**
                                            *  \file  fastDelegate.h
                                            *  \class FastDelegate
                                            *  \brief Class used for the type erasure,
                                            *  which allow the user be able to store a set of different callback's functions types with the same return type.
                                            *  \author Duroisin.L
                                            *  \version 1.0
                                            *  \date 1/02/2014
                                            */
                                            template<class R>
                                            struct FastDelegate {
                                                /**\fn default constructor
                                                */
                                                FastDelegate() = default;
                                                /**\fn FastDelegate (F&& f, Arg&& arf)
                                                *  \param F&& f : the functor to pass.
                                                *  \param Arg&&... arg : arguments to pass to the functor.
                                                */
                                                template<class F, class... Arg>
                                                FastDelegate(F&& f, Arg&&... arg) :
                                                    delegate(std::make_unique
                                                        <FastDelegateImpl<R,std::remove_reference_t<Arg>...>>
                                                        (std::forward<F>(f),std::forward<Arg>(arg)...)
                                                    )
                                                {}
                                                /**\fn FastDelegate (FastDelegate& rhs)
                                                *  \brief copy constructor.
                                                *  \param FastDelegate& rhs : the delegate to copy.
                                                */
                                                FastDelegate(FastDelegate& rhs)
                                                    : delegate(rhs.delegate->clone())
                                                {}
                                                /**\fn FastDelegate (const FastDelegate& rhs)
                                                *  \brief copy constructor.
                                                *  \param const FastDelegate& rhs : the delegate to copy.
                                                */
                                                FastDelegate(const FastDelegate& rhs)
                                                    : delegate(rhs.delegate->clone())
                                                {}
                                                /**\fn FastDelegate (FastDelegate& rhs)
                                                *  \brief move constructor.
                                                *  \param FastDelegate&& rhs : the delegate to move.
                                                */
                                                FastDelegate(FastDelegate&& rhs) =default;
                                                /**\fn FastDelegate& operator= (FastDelegate& rhs)
                                                *  \brief affect the content of the delegate to the delegate.
                                                *  \param const FastDelegate& rhs : the delegate affect.
                                                *  \return FastDelegate& : the affected delegate.
                                                */
                                                FastDelegate& operator=(const FastDelegate& rhs)
                                                { return operator=(FastDelegate(rhs)); }
                                                /**\fn FastDelegate& operator= (FastDelegate& rhs)
                                                *  \brief affect and move the content of the delegate to the delegate.
                                                *  \param const FastDelegate& rhs : the delegate to move and to affect.
                                                *  \return FastDelegate& : the moved and affected delegate.
                                                */
                                                FastDelegate& operator=(FastDelegate&&) =default;
                                                /**\fn R operator()() const;
                                                *  \brief call the std::function of the delegate.
                                                *  \return the value returned by the std::function.
                                                */
                                                template <typename... Arg>
                                                void bind(Arg&&... arg)  {
                                                     void* params = bind_impl(std::index_sequence_for<Arg...>(), static_cast<Arg&&>(arg)...);
                                                     delegate->bind(params);
                                                     delete params;
                                                }
                                                template<std::size_t... Ints, class... Args>
                                                void* bind_impl(std::index_sequence<Ints...>, Args&&... args)
                                                {
                                                    using params_t = LateParameters<ph<Ints, ArgType_t<Args>>...>;
                                                    void* params = new params_t{static_cast<Args&&>(args)...};
                                                    return params;
                                                }
                                                template<class... Arg>
                                                R operator()(Arg&&... arg)
                                                {
                                                    void* params = bind_impl(std::index_sequence_for<Arg...>(), static_cast<Arg&&>(arg)...);
                                                    return  (*delegate)(params);
                                                }
                                                /**\fn setParams(Arg&&... arg)
                                                *  \brief change the parameter's values of the delegate.
                                                *  \return Arg&&... arg : the values of the parameters of the delegate.
                                                */
                                                template<class... Arg>
                                                void setParams(Arg&&... arg)
                                                {
                                                    using DynamicType =
                                                        FastDelegateImpl<R,std::remove_reference_t<Arg>...>*;
                                                    if(dynamic_cast<DynamicType>(delegate.get()))
                                                        dynamic_cast<DynamicType>(delegate.get())->setParams(std::forward<Arg>(arg)...);
                                                    else
                                                        throw Erreur(0, "Bad cast!", 5);
                                                }
                                            private:
                                                std::unique_ptr<Delegate<R>> delegate; /**> holds the pointer to the generic delegate.*/
                                            };
                                        }
                                    }
                                    #endif



                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      19 juin 2021 à 12:21:33

                                      Il y a une fuite mémoire sur params puisqu'elle n'est jamais libérée et cela ne compile pas pour les objets sans constructeur par défaut ou avec des fonction attendant des références.

                                      struct NonDefaultConstructible
                                      {
                                        NonDefaultConstructible(int){}
                                      };
                                      
                                      
                                      FastDelegate<void> fd([](NonDefaultConstructible){ });
                                      
                                      FastDelegate<void> fd([](int&){ }, ph<0, int&>());
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        19 juin 2021 à 14:04:59

                                        jo_link_noir a écrit:

                                        Il y a une fuite mémoire sur params puisqu'elle n'est jamais libérée et cela ne compile pas pour les objets sans constructeur par défaut ou avec des fonction attendant des références.

                                        struct NonDefaultConstructible
                                        {
                                          NonDefaultConstructible(int){}
                                        };
                                        
                                        
                                        FastDelegate<void> fd([](NonDefaultConstructible){ });
                                        
                                        FastDelegate<void> fd([](int&){ }, ph<0, int&>());

                                        params je le libère ici :

                                        template <typename... Arg>
                                                    void bind(Arg&&... arg)  {
                                                         void* params = bind_impl(std::index_sequence_for<Arg...>(), static_cast<Arg&&>(arg)...);
                                                         delegate->bind(params);
                                                         delete params;
                                                    }

                                        Mais pas là mais je vais retirer cette version et forcer l'appel à bind pour passer les valeurs pour les placeholders donc je vais remplacer ça :

                                        template<class... Arg>
                                                    R operator()(Arg&&... arg)
                                                    {
                                                        void* params = bind_impl(std::index_sequence_for<Arg...>(), static_cast<Arg&&>(arg)...);
                                                        return  (*delegate)(params);
                                                    }

                                        Par ceci :

                                        R operator()()
                                                    {               
                                                        return  (*delegate)();
                                                    }

                                        Parce que je ne peux pas libérer params après le return puisqu'il sort de la fonction.

                                        Par contre je ne vois pas ce que tu veux faire ici mais c'est sûr ça ne compilera pas:

                                        struct NonDefaultConstructible
                                        {
                                          NonDefaultConstructible(int){}
                                        };
                                         
                                         
                                        FastDelegate<void> fd([](NonDefaultConstructible){ });

                                        Pour les fonctions prenant des objets en paramètre, il faut instancier l'objet et le passer au constructeur du delegate.

                                        FastDelegate<void>(&MyAppli::onMouseInside, this, sf::Vector2f(-1,-1))

                                        Ou alors utiliser un placeholder.

                                        Pour les placeholder attendant des références je n'ai pas géré ce cas là, je n'en ai jamais eu besoin pour l'instant, mais je regarderai à ça sûrement pour les amélioration future du framework.

                                        Par contre chez moi ça passe avec std::ref sans utiliser de placeholders :

                                        void test (int& i) {
                                            std::cout<<"i : "<<i<<std::endl;
                                        }
                                        int main(int argc, char* argv[])
                                        {    
                                            int i = 1;
                                            FastDelegate<void> fd(&test, std::ref(i));
                                            fd();
                                            return 0;
                                        }








                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          19 juin 2021 à 14:14:13

                                          En simplifiant un des exemples, je me suis raté. Le vrai code:

                                          using X = std::unique_ptr<int>;
                                          
                                          FastDelegate<void> fd([](X){}, ph<0, X>());
                                          
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            19 juin 2021 à 14:54:43

                                            jo_link_noir a écrit:

                                            En simplifiant un des exemples, je me suis raté. Le vrai code:

                                            using X = std::unique_ptr<int>;
                                            
                                            FastDelegate<void> fd([](X){}, ph<0, X>());
                                            


                                            Ah je me disais bien qu'utiliser une référence pour un placeholder ça me semblait bizarre parce qu'une référence doit être initialisée et donc, obligé de lui passer quelque chose lors de l'instanciation du delegate avec std::ref et donc pas de placeholder.

                                            Par contre il faut utiliser des pointeurs nus, std::unique_ptr ne fonctionne pas, je ne sais pas pourquoi, le perfect forwarding ne semble pas fonctionner

                                            template<class F>
                                                        DynamicFunction(F&& f) : Base(std::forward<F>(f))
                                                        {}



                                            C:\Program Files (x86)\ODFAEG\include\odfaeg\Core\fastDelegate.h|1018|error: no matching function for call to 'std::function<void(std::unique_ptr<int>&)>::function(void (*)(std::unique_ptr<int>))'|

                                            M'enfin je n'utilise pas de pointeurs intelligents dans mes fonctions de callback parce que ce n'est pas leur rôle de posséder les objets, mais juste les passer à d'autres fonctions.



                                            -
                                            Edité par OmbreNoire 19 juin 2021 à 14:55:10

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              3 juillet 2021 à 23:13:07

                                              'ai essayer de savoir ce qui se passe parce que je suis sûr que l'implémentation utilisant des void* est plus rapide que celle utilisant l'héritage avec fonctions virtuelles.

                                              J'ai donc écrit une fonction  de débogage pour voir ce qui se passe en affichant tout les éléments du tuple après le cast en void* :

                                              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<size_t I=0,
                                                          typename std::enable_if<(std::tuple_size<TupleArgs>::value == 0)>>
                                                          void debug() {
                                                              std::cout<<"no arguments"<<std::endl;
                                                          }*/
                                                          template<size_t I=0,class...D,
                                                          class = typename std::enable_if<(std::tuple_size<TupleArgs>::value != 0 && I < std::tuple_size<TupleArgs>::value-1 && std::is_pointer<std::tuple_element_t<I, TupleArgs>>::value)>::type>
                                                          void debug() {
                                                              std::cout<<"value : "<<I<<" :"<<std::get<I>(params)<<std::endl;
                                                              debug<I+1>();
                                                          }
                                                          template<size_t I=0, class...D, class... E,
                                                          class = typename std::enable_if<(std::tuple_size<TupleArgs>::value != 0 && I < std::tuple_size<TupleArgs>::value-1 && !std::is_pointer<std::tuple_element_t<I, TupleArgs>>::value)>::type>
                                                          void debug() {
                                                              std::cout<<"value : "<<I<<" :"<<&std::get<I>(params)<<std::endl;
                                                              debug<I+1>();
                                                          }
                                                          template<size_t I=0, class... D, class... E, class... Z,
                                                          class = typename std::enable_if<(std::tuple_size<TupleArgs>::value != 0 && I == std::tuple_size<TupleArgs>::value-1 && std::is_pointer<std::tuple_element_t<I, TupleArgs>>::value)>::type>
                                                          void debug() {
                                                              std::cout<<"value : "<<I<<" :"<<std::get<I>(params)<<std::endl;
                                                          }
                                                          template<size_t I=0, class... D, class... E, class... Z, class... G,
                                                          class = typename std::enable_if<(std::tuple_size<TupleArgs>::value != 0 && I == std::tuple_size<TupleArgs>::value-1) && !std::is_pointer<std::tuple_element_t<I, TupleArgs>>::value>::type>
                                                          void debug() {
                                                              std::cout<<"value : "<<I<<" :"<<&std::get<I>(params)<<std::endl;
                                                          }
                                                      };
                                                      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)
                                                      {
                                                          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);
                                                          };
                                                          return Data {
                                                            delegate,
                                                            storage_deleter,
                                                            &late_params_t::deleter,
                                                            new storage_t{
                                                              static_cast<DynamicFunction<R(ToStore_t<Args>&...)>&&>(f),
                                                              typename storage_t::TupleArgs{static_cast<Args&&>(args)...}
                                                            },
                                                            nullptr,
                                                            sizeof(storage_t),
                                                            0
                                                          };
                                                        }())
                                                        {
                                                          using storage_t = DelegateStorage<DynamicFunction<R(ToStore_t<Args>&...)>, ArgType_t<Args>...>;
                                                          auto& storage = *static_cast<storage_t*>(data.storage);
                                                          storage.debug();
                                                        }
                                                        FastDelegate(FastDelegate& rhs) {
                                                         char* tab1 = new char[rhs.data.storage_size];
                                                         memcpy(tab1, rhs.data.storage, rhs.data.storage_size);
                                                         char* src = (char*) rhs.data.storage;
                                                         std::cout<<"src bytes : ";
                                                         for (unsigned int i = 0; i < rhs.data.storage_size; i++)
                                                            std::cout<<(unsigned int) src[i];
                                                         std::cout<<std::endl;
                                                         std::cout<<"dst bytes : ";
                                                         for (unsigned int i = 0; i < rhs.data.storage_size; i++)
                                                            std::cout<<(unsigned int) tab1[i];
                                                         std::cout<<std::endl;
                                                         char* 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;
                                                        }
                                              

                                              Et le cast est foireux, en effet, l'adresse de mon label n'est pas la même dans le tuple et hors du tuple.

                                              std::cout<<"label address : "<<lab<<std::endl;
                                                      FastDelegate<bool> signal(&Label::isMouseInside, lab);
                                                      FastDelegate<void> slot(&ODFAEGCreator::showGUI, this, lab);
                                                      Command cmd(a, signal, slot);
                                                      lab->getListener().connect("SHOWGUI", cmd);
                                                      system("PAUSE");

                                              Comme on peut le voir clairement sur cette capture d'écran, l'adresse du label hors du tuple est 0x1040e550 tandis que l'adresse du label lorsque je l'extrait du tuple après le static_cast (ou plutôt les static_cast) est 0x56d9998 ce qui n'est clairement pas bon!!! (Par contre, comme on peut le voir, memcpy fonctionne j'ai bien la même chose en src et en dst)

                                              Et de ce fait, lorsque je récupère l'objet ici l'adresse est nulle :

                                              template<class O, class... ArgU>
                                                          R operator()(O* o, ArgU&&... arg) const
                                                          {
                                                              std::cout<<"address : "<<o<<std::endl;
                                                              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!");
                                                          }

                                              EDIT : non ma fonction de debug ne fonctionne pas et donc ce n'est pas ça le problème c'est lorsque j'utilise des itérateur sur des delegate, j'ai créé un autre sujet.



                                              -
                                              Edité par OmbreNoire 4 juillet 2021 à 12:17:26

                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                22 juillet 2021 à 9:45:27

                                                Bon, bug du compilateur mingw, avec le compilateur g++ sous linux ça ne plante pas :

                                                template <size_t I, typename T>
                                                struct ph {
                                                    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, ph<I, U>>
                                                {
                                                  using type = ph<I, U>;
                                                };
                                                
                                                template<class T>
                                                using ArgType_t = typename ArgType<T, std::remove_cv_t<T>>::type;
                                                
                                                
                                                template<class T>
                                                struct ToStoreImpl
                                                { using type = T; };
                                                
                                                template<class T>
                                                struct ToStoreImpl<std::reference_wrapper<T>>
                                                { using type = T; };
                                                template<size_t I, class T>
                                                struct ToStoreImpl<ph<I,T>>
                                                { using type = T; };
                                                
                                                template<class T>
                                                struct ToStore
                                                    : ToStoreImpl<std::remove_reference_t<T>>
                                                {};
                                                
                                                template<class T>
                                                using ToStore_t = typename
                                                    ToStore<T>::type;
                                                
                                                template<class R, class C, class... ArgT>
                                                struct DynamicWrapper {
                                                
                                                    DynamicWrapper(R(C::*pf)(ArgT...)) : pfunc(pf){}
                                                    template<class O, class... ArgU>
                                                    R operator()(O* o, ArgU&&... arg) const
                                                    {
                                                        //std::cout<<"address : "<<o<<std::endl;
                                                        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!");
                                                    }
                                                    template<class O, class... ArgU>
                                                    R operator()(O o, ArgU&&... arg) const
                                                    {
                                                        //std::cout<<"address : "<<o<<std::endl;
                                                        return (o.*pfunc)(std::forward<ArgU>(arg)...);
                                                    }
                                                private:
                                                    R (C::*pfunc)(ArgT...);
                                                };
                                                
                                                
                                                template<class F>
                                                class DynamicFunction;
                                                
                                                template<class R, class... ArgT>
                                                class DynamicFunction<R(ArgT...)>
                                                
                                                {
                                                    std::function<R(ArgT...)> func;
                                                public:
                                                    template<class F>
                                                    DynamicFunction(F&& f) : func(std::forward<F>(f))
                                                    {}
                                                
                                                    template<class C, class... ArgU>
                                                    DynamicFunction(R(C::*pf)(ArgU...))
                                                        : func(DynamicWrapper<R,C,ArgU...>(pf))
                                                    {}
                                                    /*template <typename... ArgU>
                                                    R operator()(ArgU&&... args)/* -> typename std::enable_if<std::is_void<decltype(func(std::forward<ArgU>(args)...))>::value>::type {
                                                
                                                        func(std::forward<ArgU>(args)...);
                                                    }*/
                                                    template <typename... ArgU>
                                                    R operator()(ArgU&&... args) /*-> typename std::enable_if<!std::is_void<decltype(func(std::forward<ArgU>(args)...))>::value>::type*/ {
                                                         return func(std::forward<ArgU>(args)...);
                                                    }
                                                };
                                                template<class F, class... ArgT>
                                                struct DelegateStorage {
                                                
                                                    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)
                                                {
                                                    return static_cast<T&&>(x);
                                                }
                                                template <size_t I, class T, class Params>
                                                T& get_arg(ph<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<ph<I, T>>
                                                : std::true_type
                                                {};
                                                struct LessPlaceceholder
                                                {
                                                  template<class PlaceHolder1, class PlaceHolder2>
                                                  using f = std::bool_constant<PlaceHolder1::index < PlaceHolder2::index>;
                                                };
                                                template<typename R>
                                                struct FastDelegate {
                                                    FastDelegate() {
                                                        data.delegate = nullptr;
                                                        data.params = nullptr;
                                                        data.storage_deleter = nullptr;
                                                        data.params_deleter = nullptr;
                                                        data.storage = nullptr;
                                                        data.storage_size = 0;
                                                        data.params_size = 0;
                                                        name = "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);
                                                    };
                                                    return Data {
                                                      delegate,
                                                      storage_deleter,
                                                      &late_params_t::deleter,
                                                      new storage_t{
                                                        static_cast<DynamicFunction<R(ToStore_t<Args>...)>&&>(f),
                                                        typename storage_t::TupleArgs{static_cast<Args&&>(args)...}
                                                      },
                                                      nullptr,
                                                      sizeof(storage_t),
                                                      0
                                                    };
                                                  }())
                                                  {
                                                
                                                  }
                                                  FastDelegate(FastDelegate& rhs) {
                                                   char* tab1 = new char[rhs.data.storage_size];
                                                   memcpy(tab1, rhs.data.storage, rhs.data.storage_size);
                                                   char* 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;
                                                   name = rhs.name;
                                                   //std::cout<<"FastDelegate(FastDelegate& rhs) : "<<data.params_deleter<<" : "<<name<<std::endl;
                                                  }
                                                
                                                
                                                
                                                
                                                
                                                FastDelegate(const FastDelegate& rhs) {
                                                    char* tab1 = new char[rhs.data.storage_size];
                                                    memcpy(tab1, rhs.data.storage, rhs.data.storage_size);
                                                    char* 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;
                                                    name = rhs.name;
                                                    //std::cout<<"FastDelegate(const FastDelegate& rhs) : "<<data.storage<<" : "<<name<<std::endl;
                                                }
                                                
                                                
                                                
                                                FastDelegate(FastDelegate&& rhs) {
                                                    char* tab1 = new char[rhs.data.storage_size];
                                                    memcpy(tab1, rhs.data.storage, rhs.data.storage_size);
                                                    char* 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;
                                                    name = rhs.name;
                                                    //std::cout<<"FastDelegate(FastDelegate&& rhs) : "<<data.storage<<" : "<<rhs.name<<std::endl;
                                                }
                                                
                                                FastDelegate& operator=(FastDelegate& rhs)
                                                {
                                                    char* tab1 = new char[rhs.data.storage_size];
                                                    memcpy(tab1, rhs.data.storage, rhs.data.storage_size);
                                                    char* src = (char*) rhs.data.storage;
                                                    char* 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;
                                                    name = rhs.name;
                                                    //std::cout<<"operator= (FastDelegate&) : "<<data.storage<<" : "<<name<<std::endl;
                                                    return *this;
                                                }
                                                FastDelegate& operator=(const FastDelegate& rhs)
                                                {
                                                    char* tab1 = new char[rhs.data.storage_size];
                                                    memcpy(tab1, rhs.data.storage, rhs.data.storage_size);
                                                    char* src = (char*) rhs.data.storage;
                                                    char* 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;
                                                    name = rhs.name;
                                                    //std::cout<<"operator= (const FastDelegate&) : "<<data.storage<<" : "<<name<<std::endl;
                                                    return *this;
                                                }
                                                
                                                FastDelegate& operator=(FastDelegate&& rhs) {
                                                    char* tab1 = new char[rhs.data.storage_size];
                                                    memcpy(tab1, rhs.data.storage, rhs.data.storage_size);
                                                    char* 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;
                                                    name = rhs.name;
                                                    //std::cout<<"operator=(FastDelegate&&) : "<<data.params_deleter<<" : "<<name<<std::endl;
                                                    return *this;
                                                }
                                                  template<typename... Args>
                                                  void bind(Args&&... args) {
                                                      bind_impl(std::index_sequence_for<Args...>(), std::forward<Args>(args)...);
                                                  }
                                                  template<typename... Args>
                                                  void setParams(Args&&... args) {
                                                    //std::cout<<"set params  : "<<data.storage<<" : "<<name<<std::endl;
                                                    if (data.storage) {
                                                        using storage_t = DelegateStorage<DynamicFunction<R(ToStore_t<Args>...)>, ArgType_t<Args>...>;
                                                        auto& storage = *static_cast<storage_t*>(data.storage);
                                                        storage.params = typename storage_t::TupleArgs{static_cast<Args&&>(args)...};
                                                    }
                                                  }
                                                  R operator()() {
                                                      //void* ret = nullptr;
                                                      if (data.delegate) {
                                                        return data.delegate(data);
                                                      }
                                                  }
                                                  ~FastDelegate()
                                                  {
                                                    if (data.params_deleter) {
                                                        data.params_deleter(data.params);
                                                    }
                                                    if (data.storage_deleter) {
                                                        //std::cout<<"delete storage : "<<data.storage<<" : "<<name<<std::endl;
                                                        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<ph<Ints, ArgType_t<Args>>...>;
                                                      //std::cout<<"param deleter adr : "<<&params_t::deleter<<","<<data.params_deleter<<std::endl;
                                                      //if (&params_t::deleter == data.params_deleter) {
                                                        data.params = new params_t{std::forward<Args>(args)...};
                                                        data.params_size = sizeof(params_t);
                                                      /*}
                                                      else {
                                                        std::cout<<"error ! "<<std::endl;
                                                        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;
                                                  public :
                                                  std::string name;
                                                };
                                                struct Command {
                                                    FastDelegate<void> slot;
                                                    std::unique_ptr<FastDelegate<bool>> trigger;
                                                
                                                    std::string name;
                                                    void setName(std::string name) {
                                                        this->name = name;
                                                    }
                                                    Command() {
                                                        this->trigger = nullptr;
                                                    }
                                                    Command (FastDelegate<bool> trigger, FastDelegate<void> slot) : slot(slot) {
                                                        this->trigger = std::make_unique<FastDelegate<bool>>(trigger);
                                                    }
                                                    Command(const Command& other) : slot(other.slot) {
                                                       if (other.trigger != nullptr) {
                                                           //std::cout<<"fd : "<<fd()<<std::endl;
                                                           trigger = std::make_unique<FastDelegate<bool>>(*other.trigger);
                                                            std::cout<<"command copy : "<<(*trigger)()<<std::endl;
                                                       }
                                                       name = other.name;
                                                    }
                                                
                                                    bool isTriggered()
                                                    {
                                                
                                                        if (trigger != nullptr) {
                                                            return (*trigger)();
                                                        }
                                                        return false;
                                                    }
                                                    void operator()()
                                                    {
                                                        slot();
                                                    }
                                                
                                                    Command& operator=(const Command& other) {
                                                        if (other.trigger != nullptr) {
                                                            trigger = std::make_unique<FastDelegate<bool>>(*other.trigger);
                                                            std::cout<<"command copy affector : "<<(*trigger)()<<std::endl;
                                                        }
                                                        slot = FastDelegate<void>(other.slot);
                                                        return *this;
                                                    }
                                                };
                                                class Listener {
                                                
                                                public :
                                                
                                                     Listener() {
                                                     }
                                                
                                                     void connect(std::string key, Command command) {
                                                        std::cout<<"add command"<<std::endl;
                                                        command.setName(key);
                                                        commands[key] = command;
                                                        //commands = new Command[1]{command};
                                                     }
                                                
                                                
                                                     void processEvents() {
                                                         std::map<std::string, Command>::iterator it;
                                                
                                                         for (it = commands.begin(); it != commands.end(); it++) {
                                                
                                                            if (it->second.isTriggered()) {
                                                                std::cout<<"triggered "<<std::endl;
                                                                (it->second)();
                                                            }
                                                         }
                                                         //std::cout<<commands[0].isTriggered()<<std::endl;
                                                     }
                                                     private :
                                                     std::map<std::string, Command> commands;
                                                     //Command* commands;
                                                };
                                                #include "odfaeg/Graphics/GUI/label.hpp"
                                                struct Test {
                                                    Listener listener;
                                                    odfaeg::graphic::RenderComponentManager rcm;
                                                    //odfaeg::graphic::gui::Label* lab;
                                                    Test(odfaeg::graphic::RenderWindow &rw) : rcm(rw) {
                                                        odfaeg::graphic::Font font;
                                                        font.loadFromFile("fonts/Arial.ttf");
                                                        odfaeg::graphic::gui::Label* lab = new odfaeg::graphic::gui::Label(rw, odfaeg::math::Vec3f(0, 0, 0),odfaeg::math::Vec3f(100, 50, 0),&font,"test",15);
                                                        std::cout<<"lab : "<<lab<<std::endl;
                                                        FastDelegate<bool> signal(&odfaeg::graphic::gui::Label::isMouseInside, lab);
                                                        FastDelegate<void> slot(&Test::onMouseInLab, this, lab);
                                                        Command cmd(signal, slot);
                                                        listener.connect("test", cmd);
                                                        rcm.addComponent(lab);
                                                        //std::cout<<cmd.isTriggered()<<std::endl;
                                                    }
                                                    void onMouseInLab(odfaeg::graphic::gui::Label* lab) {
                                                    }
                                                    void processEvents() {
                                                        listener.processEvents();
                                                    }
                                                };
                                                int main(int argc, char* argv[]){
                                                    odfaeg::graphic::RenderWindow rw(sf::VideoMode(800, 600), "test");
                                                    Test test(rw);
                                                    test.processEvents();
                                                    return 0;
                                                }

                                                Mais avec mingw ce code plante chez moi.

                                                • Partager sur Facebook
                                                • Partager sur Twitter

                                                static_cast foireux.

                                                × 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