Partage
  • Partager sur Facebook
  • Partager sur Twitter

template argument 1 is invalid.

two or more data types in declaration of...

Sujet résolu
    12 juin 2021 à 13:36:33

    Salut! je souhaiterais trier des éléments dans un std::tuple, j'utilise donc une structure avec un comparateur, le problème c'est que lorsque j'appelle la méta fonction du comparateur dans le std::enable_if pour savoir si je dois intervertir les éléments du tuple, j'ai des erreurs en compilation de ce style :

    C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|112|error: template argument 1 is invalid|
    C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|112|error: expected identifier before '::' token|
    C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|112|error: expected '>' before '::' token|
    C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|113|error: two or more data types in declaration of 'get'|
    C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|117|error: template argument 1 is invalid|
    C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|117|error: expected identifier before '::' token|
    C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|117|error: expected '>' before '::' token|
    C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|118|error: two or more data types in declaration of 'get'|
    ||=== Build failed: 8 error(s), 18 warning(s) (0 minute(s), 1 second(s)) ===|
    

    Avec ce code ici :

    //Sort every elements of a tuple with the specified comparator.
    template <template <class, class> class Comp, template <class> class R>
    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::f<std::tuple_element_t<I, T>, std::tuple_element_t<J, T>>::value>::type>
        auto 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::f<std::tuple_element_t<I, T>, std::tuple_element_t<J, T>>::value>::type>
        auto constexpr auto get (T tp) {
           return std::swap(std::get<I>(T()), std::get<J>(T()));
        }
        //final case second recursion and we check if the penultimate element and the last element need to be swapped.
        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 recrusion, 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, T>(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, T>(f2<I, I+1>(tp));
        }
    };

    Pourquoi il me dit que l'argument 1 du template est invalide et qu'il y a deux types ou plus dans la déclaration de get ?

    Comment compiler ce code ?

    Merci!

    EDIT : Ok c'est bon j'ai réussi! (Je m'étais trompé)

    Voilà ça trie!!! Par contre j'ai eu besoin de définir un tas d'index séquences et réfléchir ça n'étais pas si évidant que ça. 

    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>;
    };
    //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, 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, 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, template <class> class R>
    struct copy_if {
        using f = decltype(append_if<Pred, R>::template f(T()));
    };
    //Sort every elements of a tuple with the specified comparator.
    template <class Comp, template <class> class R>
    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, template <class> class R>
    struct sort {
        using f = decltype(swap_if<Comp, R>::template f(T()));
    };
    int main(int argc, char* argv[])
    {
        using late_params_t
                  = sort<LessPlaceceholder, 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>::f;
        late_params_t t = std::make_tuple(placeholder<0, int>(),placeholder<1, int>(),placeholder<2, int>(),placeholder<3, int>());
        return 0;


    Résolu, il ne me reste plus qu'à faire la structure pour virer les doublons. (Mais ça ne devrait pas trop me poser de difficultés maintenant que je sais comment faire, c'est un peu comme copy_if à part qu'il faut que j'utilise std::is_same et une double récursion comme pour swap_if.

    -
    Edité par OmbreNoire 12 juin 2021 à 17:24:23

    • Partager sur Facebook
    • Partager sur Twitter

    template argument 1 is invalid.

    × 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