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

C++ Discussion :

Template, et accesseur complexe


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 52
    Par défaut Template, et accesseur complexe
    Bonjour!
    J'ai quelques problèmes dont je ne trouve nul solution, c'est pourquoi je vous appelle à l'aide.^^
    Tout d'abord au niveau des templates:
    y a t'il un moyen de restreindre le choix du compilo au moment de remplacer les templates? C'est à dire qu'en faite j'ai :
    template <typename T>
    void Fct(T param){...}
    mais en faite je voudrais que le compilo décide entre un type string, double ou bool uniquement, c'est possible avec les template ou je dois faire pour les multitude de fct similaire que j'ai à coder, des surdefinition ?

    Ensuite un second problème me pertube, bien qu'en faite je lai plus ou moins résolu:
    J'ai fait un système de variable simple, je stock les variables dans des map<string(nom de la variable), bool( ou double, string suivant le type de la variable)>
    accesoirement j'ai une map< string(nom de variable), enum( qui défini Chaine, Nombre, Bool)> qui permet un referencement rapide de toutes les variables et de leur type.
    Enfin tous ça pour dire(et encore c'est simplifié) que sur ceux, j'ai problème d'accesseur!
    Il faudrait que je fasse une fct DonneVariable() qui renvoie soit du bool, soit du double, du string suivant le type de la variable! ( template marche pas car de toutes façon il y aurait 2 return de type différent de celui de la template).
    Ma solution c'est du #define DonneVariable() [et la on peut retourner des types différents car c'est pas une fct]

    le truc, c'est que c'est assez moche dutiliser un define pour faire une fct, nan ?
    si quelqu'un à un idée...

    Merci d'avance, Scheb

  2. #2
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Bonjour Scheb

    le compilo décide entre un type string, double ou bool uniquement
    Déjà, premier problème !
    Le compilateur ne décide pas du type à mettre dans un template. C'est l'utilisateur de la classe template qui utilise le type qu'il souhaite.

    Il existe qu'une seule façon de limiter les types utilisés dans un template : bien documenter sa classe pour que les utilisateurs sachent comment l'utiliser correctement !

    Pour le second problème, si j'ai bien compris, tu as plusieurs map (une pour chaque type). Le plus simple dans ce cas est d'écrire une fonction pour chaque map :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    string getStringVariable(string nom);
    bool getBoolVariable(string nom);
    int getIntVariable(string nom);
    Par contre, c'est pas très joli et pratique : ça suppose de connaitre le type lors de la création et lors de la récupération de la variable.

    Sinon, c'est un problème classique. Regarde du coté de boost:variant ou de Qt::QVariant.


    PS: DEFINE ? C'est encore utilisé en dehors des protections des en-têtes ?
    Il vaut mieux les éviter, ça peut poser des problèmes. Il vaut mieux utiliser des templates.

  3. #3
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Par défaut
    1) Tu peux t'inspirer de Boost.TypeTraits pour vérifier si les paramètres templates fournis sont bien du type attendu. Mais si tu n'as que 3 types, je suis plus partisan de 3 fonctions, mais il faudrait en savoir plus pour vraiment juger.

    le truc, c'est que c'est assez moche dutiliser un define pour faire une fct, nan ?
    Le truc, c'est que tout ta conception est moche. C'est plus que bancal de lister/trier toutes les variables ainsi. Sinon, il reste boost::variant comme l'a dit gbdivers
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  4. #4
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    Comme dit, le premier peut se régler à coup de Boost.Type trait et Boost.Static Assert :
    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
    #include<iostream>
    #include <string>
    #include <boost/static_assert.hpp>
     #include <boost/type_traits.hpp>
     
    template<class T>
    void a_function(T t_)
    {
        BOOST_STATIC_ASSERT((
                boost::is_same<T,bool>::value
            ||  boost::is_same<T,int>::value
            ||  boost::is_convertible<T,std::string>::value
        ));
        std::cout<<t_<<"\n";
    }
     
    int main()
    {
        std::cout<<std::boolalpha;
        a_function(true);
        a_function(1);
        a_function(std::string("aa"));
        a_function("aa"); // erreur const char* != std::string => boost::is_convertible à la place de is_same pour traiter ce cas.
        a_function(42.0); // erreur
        return 0;
    }
    Cependant, comme le dit David, si tu dois n'avoir que 3 instances et que cela ne va pas changer, j'aurais aussi tendance à préférer 3 fonctions surchargées pour bool, double et std::string.

    Pour le second, il y a probablement un petit problème de conception. Cependant, tu peux soit utiliser un boost::variant, soit un visiteur :
    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
    #include<iostream>
    #include <string>
     
    struct visiteur
    {
        virtual void do_it(double )=0;
        virtual void do_it(bool )=0;
        virtual void do_it(std::string )=0;
        protected:
        ~visiteur(){}
    };
     
    enum e_type
    {
        e_bool,
        e_string,
        e_double
    };
     
    void a_function(e_type e_, visiteur &v_)
    {
        switch(e_)
        {
            case e_bool:
            v_.do_it(true);
            break;
            case e_string:
                v_.do_it(std::string("coucou"));
            break;
            case e_double :
            v_.do_it(1.0);
            break;
        }
    }
     
    struct mon_visiteur : public visiteur
    {
        virtual void do_it(double )
        {
            std::cout<<"un double\n";
        }
        virtual void do_it(bool )
        {
            std::cout<<"un bool\n";
        }
        virtual void do_it(std::string )
        {
            std::cout<<"un string\n";
        }
    };
     
    int main()
    {
        mon_visiteur v;
        a_function(e_bool,v);
        a_function(e_string,v);
        a_function(e_double,v);
        return 0;
    }

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 52
    Par défaut
    ok merci beaucoup pour vos réponse, je pense pouvoir me débrouiller maintenant

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 52
    Par défaut
    Toutefois, je cherche toujours un moyen de demander la valeur sans connaitre son type (que ce Boost.variant, une union, les systeme de map ou n'importe qu'elle autres conceptions).
    Mais je me demande si ça n'est pas impossible (du moins trop difficile) car à ce moment là il faudrait une fonction comme ceci;

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    xxx DonneVariable(nom)
    {
    if(IsBool())
    return DonneVarBool(nom);
     
    if(IsDouble())
    return DonneVarDouble(nom);
     
    if(IsChaine())
    return DonneVarChaine(nom);
    }
    car xxx ne pourrait jamais convenir au trois en ême temps (même une template) donc je vois pas et ça m'ennui car ce serai bien plus ergonomique pour la suite...

  7. #7
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Par défaut
    Le point est que pour récupérer la valeur il faudra forcément que quelqu'un (le programmeur, une fonction, ...) connaisse son type car ta variable tu vas la récupérer dans une variable typée.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 52
    Par défaut
    Hum mais c'est à dire que oui, enfin quand tu dis qu'une fct doit connaitre le type, est ce que les fct IsBool() que j'ai mis dans l'exemple suffisent ?

    Ce serait l'interet de pas avoir a spécifier, même si on peut utiliser un intermédiaire:
    #define DonneVariable( var ) DonneValeur(var, DonneType( var ))
    (oups j'oubliais que vous aimez pas les define^^)

    En tout cas merci de m'aider.

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 52
    Par défaut
    Bon, j'ai voulu tout remettre en ordre car ça commencé à être dûr à suivre. J'ai fait un code qui synthetise le probleme ce qui peut bien aider à me comprendre^^.

    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
    #ifndef CCMS_HPP_INCLUDED
    #define CCMS_HPP_INCLUDED
     
    #include <map>
    #include <string>
     
    using namespace std;
     
    union UnionVar // c'est la valeur de la variable
    {
    	char var_chaine;
    	bool var_bool;
    };
     
    class Tata // ça m'énerve les gens fan de toto
    {
    	private:
     
    	map<string, UnionVar> map_var; //la fameuse map ! string continent le nom de la variable
     
    	public:
     
    	//jvais faire des déclarations à la vollé pour eviter un .cpp
     
    	//je mets les mutateurs à titre explicatif
    	void Mutateur(const char *variable, bool valeur)
    	{
    		map_var[variable] = valeur;
    	}
     
    	void Mutateur(const char *variable, char valeur)
    	{
    		map_var[variable] = valeur;
    	}
     
     
    	///!\\ et là survient le probleme, l'accesseurs
    	bool AccesseurBool(const char *variable)
    	{
    		return map_var[variable];
    	}
     
    	char AccesseurChaine(const char *variable)
    	{
    		return map_var[variable];
    	}
     
    	/**
            et c'est là que j'embète tout le monde!
            Je voudrais savoir, afin d'obtenir une meilleur ergonomie et facilité d'utilisation (bref du chipotage),
            si il est possible d'avoir un accesseur global grâce à je ne sais quelle technique et pas 2 de chaque type,
            c'est à dire;
     
            boolOUchar Accesseur(const char *variable)
            {
                    return map_var[variable];
            }
     
            ?*/
     
     
    };
     
    #endif // CCMS_HPP_INCLUDED
    voili voilou^^

  10. #10
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Je pense qu'un boost::variant serait ici très adapté, comme dit précedemment !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    typedef boost::variant<char, bool> my_variant;
    // ...
    map<string, my_variant> map_var;

  11. #11
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    boost.any est ton ami (ou boost.Variant si le nombre de type est limité - cf F.A.Q.) :
    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
    #include <iostream>
    #include <string>
    #include <map>
    #include <exception>
    #include <boost/any.hpp>
     
    class Tata
    {
    	private:
     
    	std::map<std::string, boost::any> map_var;
     
    	public:
    	template<class T>
    	void Mutateur(const char *variable, T valeur)
    	{
    		map_var[variable] = valeur;
    	}
     
     
    	boost::any Accesseur(const char *variable)
    	{
    		return map_var[variable];
    	}
     
    };
     
    int main()
    {
       Tata t;
       t.Mutateur("bool",true);
       t.Mutateur("char",'c');
       std::cout<<std::boolalpha<<"t[bool] = "<<
             boost::any_cast<bool>(t.Accesseur("bool")) // accès typé avec type connu
          <<"\n";
       std::cout<<std::boolalpha<<"t[char] = "<<boost::any_cast<char>(t.Accesseur("char"))<<"\n";
       try{// erreur :
          std::cout<<std::boolalpha<<"t[char] = "<<
                   boost::any_cast<bool>(t.Accesseur("char")) // si ce n'est pas le bon, ça lève une exception
               <<"\n";
       }
       catch(std::exception const &e)
       {
          std::cout<<"bad cast : "<<e.what()<<"\n";
       }
       Tata t2;
       boost::any val = t.Accesseur("bool");
       t2.Mutateur("trucmuche",val); // cependant, on peut garder des boost.any si on se 'fout' du type effectif
       std::cout<<std::boolalpha<<"t2[trucmuche] = "<<boost::any_cast<bool>(t2.Accesseur("trucmuche"))<<"\n";
       return 0;
    }

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 23/07/2011, 08h35
  2. Réponses: 7
    Dernier message: 07/04/2003, 09h35
  3. appliquer plusieurs templates
    Par Manu_Just dans le forum XSL/XSLT/XPATH
    Réponses: 7
    Dernier message: 04/04/2003, 16h26
  4. template match="node() mais pas text()"
    Par Manu_Just dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 26/03/2003, 10h52
  5. [XSLT] template
    Par demo dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 09/09/2002, 11h31

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