IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

Paramètre template non typé


Sujet :

Langage C++

  1. #21
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Fait voir le code que tu as tapé.

    Et si tu n'as jamais utilisé mpl/pp avant, je te conseilles de faire des tests pour voir comment ca fonctionne (en lisant la doc) des éléments que tu as besoin. La meta-prog (template et macro), c'est pas forcement intuitif la première fois qu'on en voit.

  2. #22
    Membre expérimenté Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Points : 1 396
    Points
    1 396
    Par défaut
    Je vois ça que c'est pas la chose la plus intuitive... Je vais aller faire des tests.
    sinon le code c'est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    #include <boost/mpl/vector.hpp>
    #include <boost/mpl/vector_c.hpp>
     
     
    #include <boost/preprocessor/repetition.hpp>
    #include <boost/mpl/at.hpp>
     
    template<class h>
    void foo_impl()
    { 
      std::cout << boost::mpl::at_c<h , 1>::type::value ; 
    }
     
    void foo()
    { foo_impl<boost::mpl::vector_c<int> >(); }
     
    #define FOO_impl(z,n,unused) \
      template<int I BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, int I)> \
      void foo() \
      { foo_impl<boost::mpl::vector_c<int, I BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, I)> >(); }
     
    BOOST_PP_REPEAT(11,FOO_impl,~)
     
    #undef FOO_impl
     
    template <class h>
    void bar()
    {
      std::cout << boost::mpl::at_c<h , 1>::type::value ; 
    }
     
    int main()
    {
      //bar< boost::mpl::vector_c<int , 1,2,3> >();
      foo<1,2,3,4,5,6,7,8,9,10,11>();

  3. #23
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    C'est normal, quand c'est instancié pour une séquence vide, tu n'as pas assez d'élément pour accéder au premier, d'où l'erreur, fait quelque chose comme ca (si tu as des erreurs du genre use of indefined type c'est un manque d'include, je te laisse trouver ceux qui faut, en regardant dans le dossier de mpl ca se fait bien) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    typedef boost::mpl::int_<2> ind;
      std::cout <<
        boost::mpl::eval_if<
          boost::mpl::less<ind,typename boost::mpl::size<Seq>::type>,
          boost::mpl::at<Seq,ind>,
          boost::mpl::int_<0> >
        ::type::value ;

  4. #24
    Membre expérimenté Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Points : 1 396
    Points
    1 396
    Par défaut
    Super les explications

    Je suis arrivé à faire ce que je voulais mais je pourrais mieux le faire. En fait, pourquoi ne peut-on pas passer "boost::mpl::size<Seq>::type::value" en argument à BOOST_PP_REPEAT ? Je suis obligé de passer directement le nombre ou alors sous forme d'un define (enfin bref c'est la même chose).

    Savez-vous quelle en est la raison ? Je n'ai rien trouvé à ce propos dans la doc.

    Merci encore !

  5. #25
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    C'est à cause de la facon dont la compilation est faite :
    - Remplacement des macros (BOOST_PP_REPEAT)
    - Instanciation des templates (boost::mpl::size<Seq>::type::value)
    - ...

    Il ne peut donc pas répéter n fois quelque chose si il ne connait pas encore n.

  6. #26
    Membre expérimenté Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Points : 1 396
    Points
    1 396
    Par défaut
    Ha d'accord, on ne sait donc pas contourner le problème ?

  7. #27
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Je ne pense pas, normalement ce n'est pas si limitant que ca, tu fixes une valeurs élévé et tu marques dans ta doc : ne pas dépasser n ou alors compiler en fixant le define MA_LIB_MAX_INT par exemple. Ou alors tu réalises différents ficher qui vont chacun à des valeurs différentes, et l'utilisteur inclu celui qu'il a besoin.

  8. #28
    Membre expérimenté Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Points : 1 396
    Points
    1 396
    Par défaut
    Oui et puis de toute façon il y a déjà BOOST_PP_LIMIT_REPEAT qui limite.

    Mais je n'utilisais plus vraiment ça comme ça, en fait je récupère les éléments template dans un tableau pour l'utiliser plus loin dans le code. Donc je fais ça comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
      template<class Seq>
    void foo_impl()
    { 
      typedef typename boost::mpl::size<Seq>::type size_t ;
     
      int weight[MAX_VALUE] ;
     
    /*
      int weight[boost::mpl::eval_if< 
          boost::mpl::less<boost::mpl::int_<0>,typename boost::mpl::size<Seq>::type>, 
          boost::mpl::at<Seq,boost::mpl::int_<0>>, 
          boost::mpl::int_<1> > 
        ::type::value] ;
     
      #define weight_imp(z,n,unused) \
      weight[n] = boost::mpl::at<Seq, boost::mpl::int_<n> >::type::value ; \ */
     
     
      #define weight_imp(z,n,unused) \
      weight[n] = boost::mpl::eval_if< \
          boost::mpl::less<boost::mpl::int_<n>,typename boost::mpl::size<Seq>::type>, \
          boost::mpl::at<Seq,boost::mpl::int_<n>>, \
          boost::mpl::int_<-1> > \
        ::type::value ; \
     
     
    BOOST_PP_REPEAT( MAX_VALUE ,weight_imp,~)
    Dans ce code je crée un tableau de MAX_VALUE alors qu'il n'y a pas nécessairement besoin. Je voulais faire comme c'est en commentaire pour ne pas avoir un tableau d'un taille inutilement grande mais bon c'est pas bien grave. Enfin si tu as une autre technique je suis preneur

    Merci !

  9. #29
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    C'est une erreur de faire ceci, tu as une sequence template, c'est connue à la compilation et ca ne prend pas de mémoire, si tu mets ca dans un tableau ca n'a plus aucun interet. Utilises directement at pour accéder aux éléments de la séquence, elle doit faire quoi ta fonction avec tout ces entiers ?

  10. #30
    Membre expérimenté Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Points : 1 396
    Points
    1 396
    Par défaut
    Au début je voulais simplement passer un tableau d'entier en paramètre mais on m'a dit que vu que c'était mieux que ce tableau soit directement connu à la compilation. On niveau du "design" de la fonction c'est pas faux et ca ne me dérange pas.

    Le problème c'est que je ne peux pas utiliser boost::mpl::at parce que ces valeurs me servent dans une boucle pour des calculs.

  11. #31
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Montre l'algo que tu veux coder, en pseudo code :
    -> Entrée : une séquence (*) d'entier
    -> A completer
    -> Sortie : rien

    (*) Peut importe la nature de la séquence : tableau, template, conteneur, autre

  12. #32
    Membre expérimenté Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Points : 1 396
    Points
    1 396
    Par défaut
    En gros c'est ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    //En entrée :
     
    array1 [n] ;
    array2 [n2] ; // Supposer être en paramètre template
     
    // Code
    sum = 0;
    for(i=0 ; i<n ; ++i)
      sum += array1[i] * array2[ i % n2] ;
     
    //Sortie 
    return sum ;

  13. #33
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Ok, est ce que tu connais les deux séquence à la compilation où juste une seule ?

  14. #34
    Membre expérimenté Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Points : 1 396
    Points
    1 396
    Par défaut
    Juste array2.

  15. #35
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    En fait c'est la partie la plus difficile : mélanger le compile-time et le run-time.

    Est-ce que la taille du premier tableau est connue à la compilation ou pas nécessairement ?

    Je l'ai fait dans le cas où ce n'est pas le cas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
     
    #include <boost/mpl/vector_c.hpp>
    #include <boost/mpl/size.hpp>
    #include <boost/mpl/for_each.hpp>
     
    #include <boost/preprocessor/repetition.hpp>
     
    #include <boost/range/adaptors.hpp>
    #include <boost/range/algorithm.hpp>
    #include <boost/range/numeric.hpp>
     
    #include <boost/phoenix/core.hpp>
    #include <boost/phoenix/operator.hpp>
     
    #include <vector>
     
    template<class Range, size_t N>
    struct Func
    {
      typedef typename boost::range_value<Range>::type val;
     
      size_t i_;
      const Range& r_;
      val& o_;
     
      Func(const Range& r, val& o) : i_(0), r_(r), o_(o) {}
      template<class T>
      void operator()(T t)
      {
        std::vector<val> v(
          boost::distance(
            r_ | boost::adaptors::sliced(i_,boost::distance(r_))
              | boost::adaptors::strided(N)
          )
        );
        boost::range::transform(
          r_ | boost::adaptors::sliced(i_,boost::distance(r_))
            | boost::adaptors::strided(N)
          , v.begin(), boost::phoenix::arg_names::arg1 * t );
        o_ = boost::accumulate(v,o_); ++i_;
      }
    };
     
    template<size_t N, class Range>
    Func<Range,N> make_func(const Range& r, typename boost::range_reference<Range>::type val)
    { return Func<Range,N>(r,val); }
     
    template<class Seq, class Range>
    typename boost::range_value<Range>::type foo_impl(const Range& r)
    { 
      typedef typename boost::range_value<Range>::type val;
      val o = val();
      boost::mpl::for_each<Seq>(make_func<boost::mpl::size<Seq>::value>(r,o));
      return o;
    }
     
    #define FOO_impl(z,n,unused) \
      template<BOOST_PP_ENUM_PARAMS(n, int I) BOOST_PP_COMMA_IF(n) class Range> \
      typename boost::range_value<Range>::type foo(const Range& r) \
      { return foo_impl<boost::mpl::vector_c<int BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, I)> >(r); }
     
    BOOST_PP_REPEAT(10,FOO_impl,~)
     
    #undef FOO_impl
    Compile et fonctionnel sur un test (faut en faire d'autre), mais surment pas optimale. J'ai utilisé boost : mpl, pp, range, phoenix, tu peux te passer de range avec les itérateurs (plus verbeux), et de phoenix si tu as le C++1x.

    L'idée a été d'inverse l'algo, à la place de prendre le modulo, je fixe l'indice du second tableau et je somme les 0<i+n2*k<n.

    Deux petites explications (faits des tests pour comprendre et pouvoir améliorer le code) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    r_ | boost::adaptors::sliced(i_,boost::distance(r_)) | boost::adaptors::strided(N)
    Permet de se promener dans la séquence en commencant à l'indice i (slice) et en ne prenant que les multiple de N (strided), donc tout les i+N*k.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    boost::mpl::for_each<Seq>(make_func<boost::mpl::size<Seq>::value>(r,o));
    Le make_func est juste un "helper" qui permet de profiter de la déduction des paramètres templates pour créer le foncteur. mpl::for_each, va appliquer le foncteur à chaque élément de la séquence (il "instancie" un élément de chaque type pour ca).

    Le foncteur va donc pour chaque i la somme sur k de a1[i+k*n2]*a2[i], puis la somme sur i, donc au final le résultat attendu (si 'jai bien compris l'algo).

    Si la taille du premier tableau est connue à la compilation on peut peut-être faire autrement, je te laisse chercher si c'est le cas.

  16. #36
    Membre expérimenté Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Points : 1 396
    Points
    1 396
    Par défaut
    Merci de ta réponse, je viens de finir de comprendre ton code et je suis presque dessus depuis que tu l'as posté (qui a dit "lent à la détente" ? ). L'algorithme utilisé me parait correct, bien qu'il faudrait faire des tests supplémentaires par exemple quand a2.size > a1.size mais bon. Et comme tu l'as bien supposé, on ne connait pas la taille de a1 à la compilation.

    Evidemment j'ai plusieurs questions :

    * Tous les algorithmes boost::adaptators::sliced, boost::range::transform, ce sont des macros ou alors c'est calculé lors du runtime ? Dans le second cas, ça doit être encore plus lent non ?... Et dans le premier cas, je vois vraiment pas comment ça marche, parce que les algorithmes utilisent des valeurs du runtime...

    * Malheureusement je pense que tu utilises une ancienne version de Boost car phoenix n'est plus disponible ici : boost/phoenix/... mais dans boost/spirit/... et impossible de retrouver la fonction que tu utilises. Enfin bref je comprend bien que c'est une lambda fonction (n'est-ce pas ?) et j'essaye d'utiliser ceci à la place :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    #include <boost/lambda/lambda.hpp>
     
     
    ((boost::lambda::_1 & 15) * boost::lambda::_2)(boost::lambda::_1, t)
     
    // ou encore....
     
    (boost::lambda::_1 * boost::lambda::_2)((boost::lambda::_1 & 15), t)
     
    // ou encore (&t)
     
    (boost::lambda::_1 * boost::lambda::_2)((boost::lambda::_1 & 15), &t)
     
    // marche mais on a virer "t"
    (boost::lambda::_1 * boost::lambda::_2)((boost::lambda::_1 & 15), 3)
    Mais sans succès; l'erreur est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    error C2664: 'boost::lambda::lambda_functor<T>::lambda_functor(const boost::lambda::lambda_functor<T> &)' : cannot convert parameter 1 from 'const boost::lambda::lambda_functor<T>' to 'const boost::lambda::lambda_functor<T> &'
    ou (en mettant "&t")

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
     error C2440: '=' : cannot convert from 'boost::lambda::detail::return_type_deduction_failure<<unnamed-symbol>>' to 'char'
    Il y a une ligne qui m'embête un peu c'est :

    D'après mes expérimentations ça initialise "o". Par contre vu que c'est "o" qu'on renvoie, il doit être du type char. Par remplacement, char o = char(); ca me semble bizarre.. J'ai du louper un truc.


    Je trouve ça super boost::range, je connaissais pas et je vais pas m'amuser à utiliser des itérateurs alors que boost::range est plus puissant.
    Par contre je pensais que je pourrais faire (grâce a Boost.Range) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    char str_[] = "123" ;
    char* str = str_ ;
    std::cout << "Check digit : " << (int)foo<1,2>(str) << std::endl;
    Dans la doc de range ils disent bien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Three types of objects are currently supported by the library:
     
        standard-like containers
        std::pair<iterator,iterator>
        built-in arrays
    Par contre je trouve pas où ils expliquent comment faire...

    Merci beaucoup.

    PS : je comprend un peu mieux ta signature maintenant

  17. #37
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    - Les adaptator/algo sont bien au runtime mais tu n'as pas le choix pour cette partie : tu ne connais le range qu'au runtime. Par contre rien en ce qui concerne la séquence template n'est calculé au runtime.

    - boost 1.47 fournit phoenix 3.0, télécharges la dernière version de boost.

    - Est bien une ligne valide, ca signifie value-initialisé la variable c de type char. Je l'ai utilisé de manière plus général avec le type val.

    -
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    int tab[] = {0,0}; //un tableau
    int* ptr = tab; //un pointeur
    Un tableau est convertible en un pointeur, mais un pointeur n'est pas un tableau. Utilises directement str_ et ca marchera.

    Edit: En faite je me suis un peu compliquer la vie, il y a plus simple et efficase :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
      template<class T, T I>
      void operator()(const boost::mpl::integral_c<T,I>&)
      {
        o_ += I * boost::accumulate(
          r_ | boost::adaptors::sliced(i_,boost::distance(r_))
            | boost::adaptors::strided(N)
          , val() );
        ++i_;
      }
    Ecrit "naivement" il y avait n opérations * et n-1 opérations +, écrit comme ceci il y a autant d'addition mais plus que n2 opérations *. Et il n'y a plus besoin du paramètre pour le foncteur. (header algorithm de range inutile avec ce code)

  18. #38
    Membre expérimenté Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Points : 1 396
    Points
    1 396
    Par défaut
    Je n'avais pas la dernière version de boost et je t'accussais, désolé. Elle est en train de builder..

    Bon sinon je pense avoir amélioré ta version (et j'ai rajouter quelques petits tests). Je sais que tu ne l'avais pas optimisé donc je ne te blâme pas.
    Je vais continuer par des affirmations corrige moi si je me trompe :

    Tu étais en O(n * 4m), je dis 4m à cause de ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    boost::accumulate(
          r_ | boost::adaptors::sliced(i_,boost::distance(r_))
            | boost::adaptors::strided(N)
    Il me semble qu'on parcourt 4 fois r_. Je dis ça à cause de boost::accumulate, boost::adaptors::* et boost::distance.

    J'ai donc essayé de corriger ça pour avoir du O(n * m), mais bon je suis pas super satisfait vu que avant j'avais du O(m), enfin on peut pas avoir le beurre et l'argent du beurre.

    Tu as une fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    template<size_t N, class Range>
    Func<Range,N> make_func(const Range& r, typename boost::range_reference<Range>::type val)
    { return Func<Range,N>(r,val); }
    à quoi sert t'elle ? dans le code en dessous j'ai réussi à m'en passer mais ça pose p-e un problème ?

    Et finalement je me demandais si boost.Range n'était manipulable que via des fonctions comme Boost::accumulate et co ? Je pense que c'est ce qui fait sa puissance mais dans le doute je demande.


    Et enfin si tu as des commentaires sur quoi que ce soit dans mon code n'hésite surtout pas.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
     
    #include <boost/mpl/vector_c.hpp>
    #include <boost/mpl/size.hpp>
    #include <boost/mpl/for_each.hpp>
     
    #include <boost/preprocessor/repetition.hpp>
     
    #include <boost/range/adaptors.hpp>
    #include <boost/range/algorithm.hpp>
    #include <boost/range/numeric.hpp>
     
    #include <boost/lexical_cast.hpp>
     
    template <size_t size_seq>
    struct sum
    {
        unsigned int pos_seq;
        unsigned int pos_range;
        unsigned int occurrences;
     
        sum(unsigned int posSeq) : pos_seq(posSeq), pos_range(1), occurrences(0) {}
     
        template<typename T>
        unsigned int operator()(unsigned int &sum, const T& t) 
        {
          unsigned int c = 0;
          try{
            c = boost::lexical_cast<unsigned int>(t);
            if(pos_range++ % (pos_seq + occurrences*size_seq) == 0)
              ++occurrences;
            else
              c = 0;
          }catch(boost::bad_lexical_cast){ } // Characters ignored.
     
          return sum + c;
        }
    };
     
    template<class Range, size_t N>
    struct Func
    {
      size_t i_;
      const Range& r_;
      unsigned int& sum_;
     
      Func(const Range& r, unsigned int &sum) : i_(0), r_(r), sum_(sum) {}
     
      template<class T, T I>
      void operator()(const boost::mpl::integral_c<T,I>&)
      {
        ++i_;
        sum_ += I * boost::accumulate(r_ , unsigned int(), sum<N>(i_) );
      }
    };
     
    template<class Seq, class Range>
    typename boost::range_value<Range>::type foo_impl(const Range& r)
    { 
      unsigned int sum = 0;
      boost::mpl::for_each<Seq>(Func<Range, boost::mpl::size<Seq>::value>(r, sum));
      return  boost::lexical_cast<boost::range_value<Range>::type>((10 - sum % 10) % 10) ;
    }
     
    #define FOO_impl(z,n,unused) \
      template<BOOST_PP_ENUM_PARAMS(n, int I) BOOST_PP_COMMA_IF(n) class Range> \
      typename boost::range_value<Range>::type foo(const Range& r) \
      { return foo_impl<boost::mpl::vector_c<int BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, I)> >(r); }
     
    BOOST_PP_REPEAT(10,FOO_impl,~)
     
    #undef FOO_impl
     
    int main()
    {
      //unsigned int number[] = {1,2,3} ;
      std::string number = "1-2-3";
      std::cout << "Check digit : " << foo<1,2,3>(number) << std::endl;
      return 0;
    }
    Merci beaucoup.

  19. #39
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    - Je ne crois pas. Les adpators ne font rien il me semble, ils ne crééent qu'un wrapper sur un range existant, mais (sauf si j'ai mal compris), ne calcul rien avant qu'on les parcours. Ainsi chaque accumulate va être en O(m/n) et le for_each est O(n), ainsi un O(n).

    - Si tu y tiens tu dois pouvoir passer d'un range à un couple d'itérateurs compatible avec la STL (cherches dans la doc et tests), mais à part si l'algo est spécifique ca ne sert à rien AMA, autant utiliser ceux de boos::range.

    - J'aurais pu me passer de cette fonction, mais par reflèxe j'ai créé une fonction qui me permet de faire un foncteur sans avoir à préciser explictement les types templates (c'est ce que fait make_func).

  20. #40
    Membre expérimenté Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Points : 1 396
    Points
    1 396
    Par défaut
    Ok.

    En tout cas un grand merci !

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. paramètres pilote non plug and play
    Par alberico dans le forum Windows XP
    Réponses: 4
    Dernier message: 17/08/2006, 20h38
  2. Réponses: 4
    Dernier message: 10/05/2006, 10h36
  3. Déclarer un paramètre template comme friend
    Par YéTeeh dans le forum Langage
    Réponses: 4
    Dernier message: 11/04/2006, 14h00
  4. X paramètres templates
    Par Alp dans le forum C++
    Réponses: 8
    Dernier message: 04/04/2006, 22h10
  5. transformer un buffer non typé en string
    Par bjl dans le forum Langage
    Réponses: 6
    Dernier message: 07/01/2006, 12h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo