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 :

Ah la simplification - généricité


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 31
    Points : 32
    Points
    32
    Par défaut Ah la simplification - généricité
    Bonjour,

    J'ai un problème simple en C++ mais je ne suis pas sûr de saisir le sens des questions:

    Problème:

    "Écrire les 4 méthodes qui retournent le minimum de deux variables passées en
    paramètre pour les types suivants int, char, float et double.
    Quel problème pose cette solution?
    Ne pourrait-elle pas être remplacée par une méthode unique générique ?
    Quelle est cependant la limite de cette seconde solution?"


    Voici ma réponse:

    -La première solution consiste a créer 4 méthode simplyInt, simplyChar, simplyFloat, simplyDouble et d'utiliser le passage d'argument par référence afin de pouvoir retourner "le minimum de deux variables"

    -La deuxième solution est apportée par le polymorphisme paramétrique ou surcharge de fonction, en créant une méthode surchargée avec les différents type int, char, float, double.

    -Il existe une troisième solution qui n'est semble-t-il pas demandée dans l'exercice, qui consiste à faire un modèle de fonction (template).

    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
     
    class simplifier
    {
     
    public:
            //Solution 1
    	int simplyInt(int &a, int &b)
    	{
    		a++, b++;
    		return 0;
    	}
     
    	int simplyChar(char &a, char &b)
    	{
    		a++, b++;
    		return 0;
    	}
     
    	int simplyFloat(float &a, float &b)
    	{
    		a++, b++;
    		return 0;
    	}
     
    	int simplyDouble(double &a, double &b)
    	{
    		a++, b++;
    		return 0;
    	}
     
            // Solution 2: Surcharge de méthode
    	int simplyf(int &a, int &b)
    	{
    		a++,b++;
    		return 0;
    	}
     
    	int simplyf(char &a, char &b)
    	{
    		a++,b++;
    		return 0;
    	}
     
    	int simplyf(float &a, float &b)
    	{
    		a++,b++;
    		return 0;
    	}
     
    	int simplyf(double &a, double &b)
    	{
    		a++,b++;
    		return 0;
    	}
    	// Solution 3: les templates
    	template <typename T>
    	T Tsimply(T &a, T &b)
    	{
     
    		a++,b++;
    		return 0;
    	}
     
    };
    Quelle est la différence entre la généricité apportée par la surcharge de méthode et la généricité apportée par les templates de fonctions.

    Pensez-vous que le problème attend la solution 2 ou la solution 3 comme réponse ?

    Je ne vois pas quoi répondre à la troisième question ... si ce n'est que pour la solution 2, il est nécessaire d'écrire le code de fonctions pour chaque combinaison de type.

    Merci d'avance
    Eh eH EH!!! GrnaGrnaGnnnnn!!

  2. #2
    Membre actif

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    Si l'énoncé est tel quel, il faut créer 4 fonctions prenant (pour la première) deux char en arguments et retournant un char égal au minimum des deux char. Tu peux soit passer par référence constante soit par valeur. Tu donnes les noms que tu veux : 4 méthodes n'implique pas des noms différents.

    Problème : indice : la question 1 est fastidieuse.

    Solution : template.

    Limite : il est nécessaire que le typename possède ... Sinon, le compilateur n'appreciera pas

  3. #3
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par azman0101 Voir le message
    -La première solution consiste a créer 4 méthode simplyInt, simplyChar, simplyFloat, simplyDouble et d'utiliser le passage d'argument par référence afin de pouvoir retourner "le minimum de deux variables"
    Pourquoi un passage par argument ? Pourquoi des fonctions avec un nom différent ?

    Citation Envoyé par azman0101 Voir le message
    -La deuxième solution est apportée par le polymorphisme paramétrique ou surcharge de fonction, en créant une méthode surchargée avec les différents type int, char, float, double.
    Ma compréhension du problème me fait dire que ces fonctions sont la réponse à la première question :

    Écrire les 4 méthodes qui retournent le minimum de deux variables passées en
    paramètre pour les types suivants int, char, float et double.
    Citation Envoyé par azman0101 Voir le message
    -Il existe une troisième solution qui n'est semble-t-il pas demandée dans l'exercice, qui consiste à faire un modèle de fonction (template).
    Si cette solution est demandé, c'est la troisième question :

    Ne pourrait-elle pas être remplacée par une méthode unique générique ?
    Citation Envoyé par azman0101 Voir le message
    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
     
    class simplifier
    {
     
    public:
            //Solution 1
    	int simplyInt(int &a, int &b)
    	{
    		a++, b++;
    		return 0;
    	}
     
    	int simplyChar(char &a, char &b)
    	{
    		a++, b++;
    		return 0;
    	}
     
    	int simplyFloat(float &a, float &b)
    	{
    		a++, b++;
    		return 0;
    	}
     
    	int simplyDouble(double &a, double &b)
    	{
    		a++, b++;
    		return 0;
    	}
     
            // Solution 2: Surcharge de méthode
    	int simplyf(int &a, int &b)
    	{
    		a++,b++;
    		return 0;
    	}
     
    	int simplyf(char &a, char &b)
    	{
    		a++,b++;
    		return 0;
    	}
     
    	int simplyf(float &a, float &b)
    	{
    		a++,b++;
    		return 0;
    	}
     
    	int simplyf(double &a, double &b)
    	{
    		a++,b++;
    		return 0;
    	}
    	// Solution 3: les templates
    	template <typename T>
    	T Tsimply(T &a, T &b)
    	{
     
    		a++,b++;
    		return 0;
    	}
     
    };
    Aucune de ces fonctions ne retournent le minimum entre deux nombres.

    Citation Envoyé par azman0101 Voir le message
    Quelle est la différence entre la généricité apportée par la surcharge de méthode et la généricité apportée par les templates de fonctions.
    La surcharge de fonction n'est pas de la généricité. Tu n'as pas une fonction générique mais n fonctions ayant le même nom.

    Citation Envoyé par azman0101 Voir le message
    Pensez-vous que le problème attend la solution 2 ou la solution 3 comme réponse ?
    Voir ci-dessus.

    Citation Envoyé par azman0101 Voir le message
    Je ne vois pas quoi répondre à la troisième question ... si ce n'est que pour la solution 2, il est nécessaire d'écrire le code de fonctions pour chaque combinaison de type.
    Parles-tu bien de cette question :

    Quelle est cependant la limite de cette seconde solution?
    Si oui, voir la réponse de NoIdea.

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 31
    Points : 32
    Points
    32
    Par défaut
    Merci !! je n'avais pas bien compris la question "qui retournent le minimum de deux variables passées" où avais-je la tête !

    j'avais fait quatre méthodes car il me semblait que l'énoncé demandait 4 méthodes "différentes".

    Maintenant, ma réponse 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
     
    class simplifier
    {
     
    public:
            // Solution 2: Surcharge de méthode
    	int simplyf(int a, int b)
    	{
    		return a < b ? a : b;
    	}
     
    	char simplyf(char a, char b)
    	{
    		return a < b ? a : b;
    	}
     
    	float simplyf(float a, float b)
    	{
    		return a < b ? a : b;
    	}
     
    	double simplyf(double &a, double &b)
    	{
    		return a < b ? a : b;
    	}
     
    };
    Quel problème pose cette solution?

    il est nécessaire d'écrire le code de fonctions pour chaque combinaison de type.


    Ne pourrait-elle pas être remplacée par une méthode unique générique ?

    Oui en utilisant les templates de fonctions:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    class simplifier
    {
     
    public:
    	// Solution 2: les templates
    	template <typename T>
    	T Tsimply(T a, T b)
    	{
    		return a < b ? a : b;
    	}
     
    };

    Quelle est cependant la limite de cette seconde solution?
    il est nécessaire que le typename possède un opérateur de comparaison


    Merci
    Eh eH EH!!! GrnaGrnaGnnnnn!!

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

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut
    Pour aller plus loin, même si ce n'est pas demandé par l'exercice, on peut envisager le cas de deux types différents !
    Par contre, nouveau problème : quel type renvoyer ? T ? U ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    template <typename T, typename U>
    ???? MyOp(T a, U b)
    {
    	return a < b ? a : b;
    }
    Réponse : classe de trait !

  6. #6
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par azman0101 Voir le message
    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
     
    class simplifier
    {
     
    public:
            // Solution 2: Surcharge de méthode
    	int simplyf(int a, int b)
    	{
    		return a < b ? a : b;
    	}
     
    	char simplyf(char a, char b)
    	{
    		return a < b ? a : b;
    	}
     
    	float simplyf(float a, float b)
    	{
    		return a < b ? a : b;
    	}
     
    	double simplyf(double &a, double &b)
    	{
    		return a < b ? a : b;
    	}
     
    };
    Pourquoi mettre ces fonctions dans une classe ?
    Et même si tu veux les mettre dans une classe, il faudrait plutôt les mettre statiques.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  7. #7
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par poukill Voir le message
    Pour aller plus loin, même si ce n'est pas demandé par l'exercice, on peut envisager le cas de deux types différents !
    Par contre, nouveau problème : quel type renvoyer ? T ? U ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    template <typename T, typename U>
    ???? MyOp(T a, U b)
    {
    	return a < b ? a : b;
    }
    Réponse : classe de trait !
    La classe de traits ne sera pas capable de faire le choix correct. Elle permettre de faire un choix cohérent (le "meilleur" type sur les deux passés en paramètre), mais le "meilleur" type n'est pas nécessairement le bon. C++0x ne fera pas mieux, puisque le bon type n'est connu qu'au runtime (donc trop tard pour le compilateur).

    Du coup, il est préférable de laisser le choix à l'utilisateur (c'est pour ça que std::min, std::max, ... ne prennent qu'un seul type : c'est à l'utilisateur de faire le choix du type de retour, en précisant si besoin le type unique des paramètres avec un cast dans le cas où des incompatibilités surgisses (signed vs. unsigned, ...).
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  8. #8
    Invité
    Invité(e)
    Par défaut
    C++0x ne fera pas mieux, puisque le bon type n'est connu qu'au runtime (donc trop tard pour le compilateur).
    A moins de n'avoir rien compris à ta réponse je ne vois pas pourquoi le type de l'expression a < b ? a : b n'est pas le plus satisfaisant ? De toutes façon a et b doivent avoir le même type ou pouvoir être convertis implicitement dans en un même type pour être utilisé dans une ternaire, non ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    template <typename T, typename U>
    auto MyOp(T a, U b) -> decltype(a < b ?  a : b)
    {
    	return a < b ? a : b;
    }

  9. #9
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    J'ai du mal à voir un exemple où c'est intéressant au runtime, mais le type de "a # b ? a : b" (# == < ou >) n'est pas forcément l'idéal.

    Par exemple, si a est unsigned int, et b est int, pour min, on voudrait int, pour max on voudrait unsigned int, or dans les deux cas, l'expression "a # b ? a : b" a le même type.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  10. #10
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par Joe Dralliam Voir le message
    A moins de n'avoir rien compris à ta réponse je ne vois pas pourquoi le type de l'expression a < b ? a : b n'est pas le plus satisfaisant ? De toutes façon a et b doivent avoir le même type ou pouvoir être convertis implicitement dans en un même type pour être utilisé dans une ternaire, non ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    template <typename T, typename U>
    auto MyOp(T a, U b) -> decltype(a < b ?  a : b)
    {
    	return a < b ? a : b;
    }
    decltype renverra toujours le même type, or selon les valeurs de a et b, tu peux vouloir obtenir le type de a ou le type de b. JoliLoic le dit fort bien, et là je tape ma réponse sur un iPhone, donc je ne vais pas m'étendre davantage
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

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

Discussions similaires

  1. [architecture] pour de la généricité, vous feriez quoi ?
    Par Alec6 dans le forum Débats sur le développement - Le Best Of
    Réponses: 39
    Dernier message: 03/07/2006, 14h39
  2. [D7] généricité / portabilité d'une application
    Par Magnus dans le forum Bases de données
    Réponses: 7
    Dernier message: 01/09/2005, 08h39
  3. [Ada 95] Généricité de type/package
    Par kindool dans le forum Ada
    Réponses: 5
    Dernier message: 19/05/2005, 11h54
  4. Simplification d'une requête UNION
    Par eautret dans le forum Langage SQL
    Réponses: 6
    Dernier message: 18/01/2005, 14h51
  5. [Kylix] Simplifications de l'écriture Kylix/Pascal"
    Par Mr Vincent KLEIN dans le forum EDI
    Réponses: 1
    Dernier message: 11/03/2003, 11h07

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