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 :

Ensemble de paramètre template "désactivables" et métaprogrammation.


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert 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
    Par défaut Ensemble de paramètre template "désactivables" et métaprogrammation.
    Bonsoir

    J'ai une fonction qui prend pas mal de paramètres template qui sont en fait des types de foncteur. Par exemple,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template <typename skipping_condition, 
    		  typename required_condition,
    		  typename seq_iterator>
    std::size_t function(seq_iterator seq_begin, seq_iterator seq_end)
    {	
    }
    skipping_condition et required_condition sont deux foncteurs booléens prenant un ou deux paramètres (d'où mon thread de cet aprem : ici).

    La fonction ci-dessus encapsule la skipping condition dans un filter_iterator et appelle la même fonction sans le paramètre template encapsulé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <typename required_condition,
    		  typename seq_iterator>
    std::size_t function(seq_iterator seq_begin, seq_iterator seq_end)
    {	
    }
    Et vu qu'il y a plus que 2 paramètres templates, ce "dépilage" de template continue encore en encapsulant chaque fois une condition dans un filter ou transform_iterator.

    J'aimerais trouver un moyen qui me permette de rentre optionnel ces conditions en passant par une structure "no_skipping_condition" par exemple. L'effet serait d'ignorer ce paramètre template et de ne pas l'encapsuler dans un itérateur.

    Alors évidemment on peut utiliser typeid ou d'autre RTTI. Il faut que ça soit fait à la compilation...


    Ensuite j'ai un deuxième problème (en quelque sorte similaire au premier) qui a émané suite à mon premier poste.

    Considérons la fonction suivante :

    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
    template<typename skipping_condition,
    typename required_condition,
    ....
    >
    std::size_t checksum(seq_iterator seq_begin, seq_iterator seq_end, counter_type &counter)
    {	
      if(function_trait<skipping_condition>::arity == 1)
      {
        checksum<required_condition, ..., seq_iterator>(boost::filter_iterator(skipping_condition, seq_begin, seq_end),
    	                                               boost::filter_iterator(skipping_condition, seq_end, seq_end),
    												   counter);
      }
      if(function_trait<skipping_condition>::arity == 2)
      {
        checksum<required_condition, ..., seq_iterator>(boost::filter_iterator(boost::bind(skipping_condition, boost::bind(deref<counter_type>, counter)), seq_begin, seq_end),
    	                                               boost::filter_iterator(boost::bind(skipping_condition, boost::bind(deref<counter_type>, counter)), seq_end, seq_end),
    												   counter);
      }
    }
     
    template<class T> T& deref( T* p ) { return *p; }
    Le problème c'est que vérifier l'arité de la fonction est une vérification du runtime alors qu'il me faut vérifier tout ça au compile-time... J'ai bien regardé du côté de boost::mpl mais je ne trouve pas LA fonction qui fera mon bonheur

    J'espère que j'ai été assez clair sur ce que je n'arrivais pas à faire.

    Merci pour vos réponses.

  2. #2
    Membre Expert

    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 : 34
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Je ne suis pas certain de bien comprendre ton problème, mais tu pourrais introduire des classes NoSkipping, NoRequired et utiliser la spécialisation (classe de trait, de politique) pour définir des comportements dépendant de ceux-ci au besoin?

    Pourtant il y a bien un if_ dans mpl, par contre ca te retourne un type, il te reste à bien choisir les types pour qu'il réalise le résultat souhaité.

  3. #3
    Membre Expert 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
    Par défaut
    Effectivement la spécialisation est la solution mais j'ai vu qu'on ne pouvait pas spécialiser partiellement des fonctions ? Je me trompe ?

    Et qu'en est-il du 2ème problème ? Je viens de voir l'édit du message. Avec le if_c mais j'ai du mal à voir comment un type peut faire le boulot d'une fonction, avec des membres statiques ?

  4. #4
    Membre Expert

    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 : 34
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Pour le second j'ai édité mon message précédent.

    Oui tu ne peux pas spécialiser partiellement une fonction, mais tu peux le faire pour les classes de trait / de politique, et utiliser celle-ci dans ta fonction.

  5. #5
    Membre Expert

    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 : 34
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Avec le if_c mais j'ai du mal à voir comment un type peut faire le boulot d'une fonction
    Tu peux aussi instancier la classe et appeler une méthode. Par contre fais attention à l'écriture de ta fonction, essaies de garder le maximum de points de variations (que tu puisses changer le comportement de ton algo sans devoir réécrire l'ensemble des tes classes).

  6. #6
    Membre Expert 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
    Par défaut
    Bonjour et merci pour tes réponses Flob90.

    J'ai un peu "joué" avec tout ça cette nuit et ce matin et je suis amené à me poser plusieurs questions :

    1. Tout d'abord, est-ce une bonne idée de passer des fonctions (foncteurs) en paramètres template. J'étais parti la dessus parce que j'en avais quand même pas mal (4 fonctions) à passer en paramètres.
    2. Du coup, en testant, je me suis rendu compte qu'on ne peut pas passer une fonction en argument template (logique vu qu'une fonction est un pointeur me direz-vous). Donc, c'est encore un doute de plus sur le fait que peut-être il serait plus intéressant de le passer en paramètre avec instanciation préalable.
    3. Mais par rapport à au dessus, comment faire pour encapsuler facilement une fonction dans un type ?


    Vu que vous m'aviez parlé des traits, j'ai décidé de les utiliser, et plus je codais plus je trouvais ça bien. Mais bon je m'étais un peu trop cru au pays des bisounours...

    J'ai fait les codes suivant :

    L'appel des classes de trait doit se passer comme suit :

    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
    template <typename skipping_condition, 
    		  typename required_condition,
    		  typename transform_function,
    		  typename checksum_function,
    		  typename size_contract, 
    		  typename counter_type,
    		  typename seq_iterator>
    std::size_t checksum(seq_iterator seq_begin, seq_iterator seq_end, counter_type &counter)
    {
      typedef condition_trait<skipping_condition, boost::filter_iterator> cond;
     
      return checksum<required_condition, 
                              transform_function,
    		          checksum_function, 
    			  size_contract, 
    		          counter_type> (cond::begin(seq_begin, seq_end, counter), 
    				                cond::end(seq_end, counter),
    						counter);
    }
    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
    struct no_arg{};
     
    template <typename function, 
              typename result_type = boost::function_traits<function>::result_type,
              typename arg1_type = boost::function_traits<function>::arg1_type,
    	  std::size_t arity = boost::function_traits<function>::arity>
    struct arity_trait;
     
    template <typename unary_function, 
              typename result_type = boost::function_traits<unary_function>::result_type,
    	  typename arg1_type = boost::function_traits<unary_function>::arg1_type,
    	  std::size_t arity = boost::function_traits<unary_function>::arity>
    struct arity_trait<unary_function, result_type, arg1_type, 1>
    {
      typedef unary_function type;
     
      template <typename bind_arg>
      static type bind_function(unary_function f, bind_arg&)
      {
        return f;
      }
    };
     
    template <typename binary_function, 
              typename result_type = boost::function_traits<binary_function>::result_type,
    	  typename arg1_type = boost::function_traits<binary_function>::arg1_type,
    	  std::size_t arity = boost::function_traits<binary_function>::arity>
    struct arity_trait<binary_function, result_type, arg1_type, 2>
    {
      typedef boost::function<result_type(arg1_type)> type;
     
      template <typename bind_arg>
      static type bind_function(binary_function f, bind_arg& arg)
      {
        return boost::bind(f(), boost::bind(deref<bind_arg>, arg));
      }
    };
     
    template <typename function, typename iterator>
    struct condition_trait
    {
      template <typename base_iterator, typename bind_arg>
      static iterator<function, base_iterator> begin(base_iterator b, base_iterator e, bind_arg &arg)
      {
        typedef arity_trait<function> binding;
        return iterator<binding::type, base_iterator>(binding::bind_function(function(), arg), b, e);
      }
     
      template <typename base_iterator, typename bind_arg>
      static iterator<function, base_iterator> end(base_iterator b, base_iterator e, bind_arg &arg)
      {
        typedef arity_trait<function> binding;
        return iterator<binding::type, base_iterator>(binding::bind_function(function(), arg), e, e);
      }
    };
     
    template <typename condition, typename iterator>
    struct condition_trait<no_arg, iterator>
    {
      template <typename base_iterator, typename bind_arg>
      static base_iterator& begin(base_iterator &b, base_iterator &, bind_arg&) 
      {
        return b;
      }
     
      template <typename base_iterator, typename bind_arg>
      static base_iterator& end(base_iterator &e, bind_arg&) 
      {
        return e;
      }
    }
    Premièrement il y a une spécialisation de condition_trait pour gérer le cas où il n'y a pas besoin de condition.
    Ensuite il y a arity_trait qui permet de séparer les fonctions unaire et binaire.

    Je ne sais plus comment faire, il doit surement y avoir un problème dans mon raisonnement et peut-être que j'essaye de faire des choses impossibles ou que je les simplifie trop.

    En bref : .

    Merci

  7. #7
    Membre Expert
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Par défaut
    Citation Envoyé par Trademark Voir le message
    comment un type peut faire le boulot d'une fonction, avec des membres statiques ?
    bah tu l'instancie et tu appelels son operator()()

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Requete paramétrée avec des singles quotes ?
    Par Mirmillon dans le forum Bases de données
    Réponses: 5
    Dernier message: 03/12/2010, 11h34

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