Partage
  • Partager sur Facebook
  • Partager sur Twitter

Récursion et spécialisation de structures.

    13 juin 2021 à 4:10:50

    Bonjour! Je souhaite faire ceci mais avec des structures pour éviter l'instanciation de tuple qui pose problème car il faut que les types aient un constructeur par défaut :

    //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 {
                T tp;
                using f = decltype(append_if<Pred>::template f(tp));
            };
            template<template <class...> class Pred>
            struct copy_if <Pred, std::tuple<>> {
                using f = std::tuple<>;
            };

    J'ai donc écrit le code suivant, mais ça ne fonctionne pas!!!

    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...>)
    {
     using type = std::tuple<std::tuple_element_t<Ints, T>...>;
    }
    //Remove the Nth elements of a tuple.
    template<std::size_t N, typename T>
    struct remove_Nth
    {
      static 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>;
      using type = decltype(select_tuple<T>(indices{}));
    };
    template <size_t I, class T, bool B>
    struct get;
    template <size_t I, class T>
    struct get <I, T, true> {
        using type = T;
    };
    template <size_t I, class T>
    struct get <I, T, false> {
        using type = typename remove_Nth<I, T>::type;
    };
    template <template<class...> class Pred, class T, class Seq>
    struct append_if {
        using f = typename append_if<Pred, T, Seq>::f;
    };
    template <template<class...> class Pred, class T, size_t... I>
    struct append_if  <Pred, T, std::index_sequence<I...>> {
        using f = typename append_if<Pred, T, std::index_sequence<I...>>::f;
    };
    template <template<class...> class Pred, class T, size_t IH, size_t... IT>
    struct append_if<Pred, T, std::index_sequence<IH, IT...>> {
        using f = typename get<IH, T, Pred<std::tuple_element_t<IH, T>>::value>::type;
    };
    template<template <class...> class Pred, typename T>
    struct copy_if {
        using f = typename append_if<Pred, T, std::make_index_sequence<std::tuple_size<T>()-0>>::f;
    };
    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<3, int>, int, placeholder<2, int>, float, 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;*/
        tuple_t tp = std::make_tuple(placeholder<3, int>(),placeholder<2, int>(),placeholder<1, int>(),placeholder<0, int>());
        return 0;
    }
    C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|114|error: conversion from 'tuple<placeholder<3, int>, placeholder<2, int>, placeholder<1, int>, placeholder<0, int>>' to non-scalar type 'tuple<placeholder<3, int>, int, placeholder<2, int>, float, placeholder<1, int>, char, placeholder<0, int>>' requested|

    Lorsque j'inverse la condition ici :

    template <size_t I, class T, bool B>
    struct get;
    template <size_t I, class T>
    struct get <I, T, false> {
        using type = T;
    };
    template <size_t I, class T>
    struct get <I, T, true> {
        using type = typename remove_Nth<I, T>::type;
    };

    J'ai une autre erreur. (sûrement parce que le tuple est vide et qu'il n'y a pas de types)

    C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|114|error: variable or field 'tp' declared void|

    Je pense donc qu'il fait donc bien la récursion, mais, la spécialisation de get ne fonctionne pas pour true et false pourtant ::vallu de std::true_type ou std::false_type me retourne bien true ou false non ?

    • Partager sur Facebook
    • Partager sur Twitter
      14 juin 2021 à 5:27:35

      J'ai corrigé quelques erreurs dans le code mais j'ai un autre soucis j'ai besoin de récupérer le type du nouveau tuple pour le passer à la spécialisation suivante j'ai donc quelque chose du genre :

      template <template<class>class pred, class t, size_t ih, size_t... tu>

      struct remove_if {

      using f = remove_if <pred, get<...>, it...>::f;

      Le problème c'est que la spécialisation suivante n'est pas encore définie donc le compilateur râle. 

      Et je pense pas qu'il y aie moyen de faire une déclaration anticipée.

      -
      Edité par OmbreNoire 14 juin 2021 à 7:00:29

      • Partager sur Facebook
      • Partager sur Twitter
        16 juin 2021 à 20:33:12

        Mon idée ne fonctionne pas il ne peut pas déduire le type de la structure avec le nouveau tuple comme c'est le cas dans une fonction avec le mot clé auto :

        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, typename Seq>
        struct select_tuple;
        template<typename T, size_t... Ints>
        //Return a tuple with elements at indexes.
        struct select_tuple<T, std::index_sequence<Ints...>>
        {
         using type = std::tuple<std::tuple_element_t<Ints, T>...>;
        };
        //Remove the Nth elements of a tuple.
        template<std::size_t N, typename T>
        struct remove_Nth
        {
          static 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>;
          using type = select_tuple<T, indices>;
        };
        template <size_t I, class T, bool B>
        struct get;
        template <size_t I, class T>
        struct get <I, T, true>
        {
            static void print() {
                std::cout<<"true selected"<<std::endl;
            }
            using type = T;
        };
        template <size_t I, class T>
        struct get <I, T, false> {
            static void print() {
                std::cout<<"false selected"<<std::endl;
            }
            using type = typename remove_Nth<I, T>::type;
        };
        template <template<class...> class Pred, class T, bool B, size_t NB, class Seq>
        struct append_if;
        template <template<class...> class Pred, class T, bool B, size_t NB, size_t... I>
        struct append_if  <Pred, T, B, NB, std::index_sequence<I...>> {
            using f = typename append_if<Pred, T, B, NB, std::index_sequence<I...>>::f;
        };
        template <template<class...> class Pred, class T, bool B, size_t NB, size_t IH, size_t... IT>
        struct append_if<Pred, T, B, NB, std::index_sequence<IH, IT...>> {
            using f = typename append_if<Pred, typename get<IH-NB, T, Pred<std::tuple_element_t<IH-NB, T>>::value>::type, B, NB, std::index_sequence<IH, IT...>>::f;
        };
        template <template<class...> class Pred, class T, size_t NB, size_t IH, size_t... IT>
        struct append_if<Pred, T, true, NB, std::index_sequence<IH, IT...>> {
            using f = typename append_if<Pred, typename get<IH-NB, T, Pred<std::tuple_element_t<IH-NB, T>>::value>::type, Pred<std::tuple_element_t<IH-NB, T>>::value, NB, std::index_sequence<IH, IT...>>::f;
        };
        template <template<class...> class Pred, class T, size_t NB, size_t IH, size_t... IT>
        struct append_if<Pred, T, false, NB, std::index_sequence<IH, IT...>> {
            using f = typename append_if<Pred, typename get<IH-NB, T, Pred<std::tuple_element_t<IH-NB, T>>::value>::type, Pred<std::tuple_element_t<IH-NB, T>>::value, NB+1, std::index_sequence<IH, IT...>>::f;
        };
        template <template<class...> class Pred, class T,bool B, size_t NB, size_t IH>
        struct append_if<Pred, T, B, NB, std::index_sequence<IH>> {
            using f = typename get<IH-NB, T, Pred<std::tuple_element_t<IH-NB, T>>::value>::type;
        };
        template <template<class...> class Pred, class T,bool B, size_t NB>
        struct append_if<Pred, T, B, NB, std::index_sequence<>> {
            using f = T;
        };
        template<template <class...> class Pred, typename T>
        struct copy_if {
            using f = typename append_if<Pred, T, Pred<std::tuple_element_t<0, T>>::value, 0, std::make_index_sequence<std::tuple_size<T>()-0>>::f;
        };
        template<template <class...> class Pred>
        struct copy_if <Pred, std::tuple<>> {
            using f = std::tuple<>;
        };
        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<3, int>, int, placeholder<2, int>, float, 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;
            tuple_t tp = std::make_tuple(placeholder<3, int>(),placeholder<2, int>(),placeholder<1, int>(),placeholder<0, int>());
            return 0;
        }

        J'ai une erreur du style invalid use of incomplete type 'struct append_if<....>'

        Je vais laissé tombé parce que sans l'instanciation ça me semble compliqué, le principe de kvasir semble intéressant mais je ne le comprend pas :

        Dans ce lien : https://jonathanpoelen.github.io/2018/11/meta-fonction-et-continuation/

        si je reprend ce code :

        template<class F, class... Ts>
        using call = typename F::template f<Ts...>;
        
        template<class C>
        struct add_const
        {
          template<class T>
          using f = call<C, T const>;
        };
        
        template<class C>
        struct add_lvalue_reference
        {
          template<class T>
          using f = call<C, T&>;
        };

        Il faut que C passé à la structure call contienne un using f avec un template variadique hors elle n'en contient pas.

        Même chose ici dans la librairie mp.hpp :

        /// \cond
            namespace detail
            {
                template <class L> struct _unpack {};
                template <class L> struct _unpack_append {};
            }
            /// \endcond
        
            /// \ingroup utility
        
            /// Turns a \typelist into a \sequence of those types.
            /// \semantics
            ///   \code
            ///   unpack<F>::f<typelist<xs...>, ys...> == F::f<ys..., xs...>
            ///   \endcode
            /// \treturn \sequence
            template<class C>
            struct unpack
            {
                template<class seq, class... xs>
                using f = typename detail::_unpack<seq>::template f<C, xs...>;
            };

        Il faut que _unpack contienne un using  f et un template variadique hors elle n'en contient pas et ça compile quand même.

        Je ne sais pas du tout du coup quel code vont générer ces structures.

        Et pour ce code :

        template<class T>
        struct decay
        {
          using type = call<
            if_<
              cfl<std::is_array>,
              cfe<std::remove_extent, cfe<detail::add_pointer_impl>>,
              if_<
                cfl<std::is_function>,
                cfe<std::add_pointer>,
                cfe<std::remove_cv>
              >
            >,
            std::remove_reference_t<T>
          >;
        };



        namespace detail
        {
          template<bool B>
          struct conditional;
        }
        
        template<class P, class TC, class FC>
        struct if_
        {
          template<class... Ts>
          using f = call<call<detail::conditional<call<P, Ts...>::value>, TC, FC>, Ts...>;
        };
        
        template<template<class...> class F, class C = identity>
        struct cfl
        {
          template<class... Ts>
          using f = call<C, F<Ts...>>;
        };
        
        template<template<class...> class F, class C = identity>
        struct cfe
        {
          template<class... Ts>
          using f = call<C, typename F<Ts...>::type>;
        };
        
        
        namespace detail
        {
          template<bool B>
          struct conditional
          {
            template<class T, class U> using f = T;
          };
        
          template<>
          struct conditional<false>
          {
            template<class T, class U> using f = U;
          };
        }

        Je ne sais même pas ce que sont les eager et lazy méta fonctions, call ne contient pas de using nommé value, et le type c'est call<...> normalement mais là on dirait qu'il retire le type de la structure englobante tout seul enfin soit je ne comprend absolument rien.

        -
        Edité par OmbreNoire 16 juin 2021 à 20:35:27

        • Partager sur Facebook
        • Partager sur Twitter

        Récursion et spécialisation de structures.

        × 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