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 :

Exercice C++ : des push_back transactionnels [Débat]


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    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 Exercice C++ : des push_back transactionnels
    Bonjour à tous

    J'ai posé un petit exercice sur le chat en pensant qu'il ne poserait pas de difficultés particulière. Et j'ai été surpris de voir une proposition de solution assez originale de germinolegrand (qu'il va garder pour lui, le temps que d'autres personnes proposent aussi des solutions). Voici l’annoncé, relativement simple, pour que d'autres puisse participer :

    Vous avez un classe qui contient plusieurs conteneurs membres. Vous souhaitez écrire une fonction permettant de faire une transaction, c'est à dire insérer des éléments dans les conteneurs et que les insertions soient toutes réussies ou soient toutes annulées.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class SafeTransaction {
       vector<int> v1, v2;
    public:
       void push_back(int x1, int x2) { 
          v1.push_back(x1);
          v2.push_back(x2);
       }
    };
     
    SafeTransaction t;
    t.push_back(1, 2);
    // v1 et v2 contiennent 1 élément chacun, soit v1 et v2 ne contiennent rien
    Pouvez-vous donner un exemple de classe(s) permettant de réaliser ça ?
    Pensez en particulier aux exceptions, à pouvoir utiliser différents types de conteneurs et de contenant et plus de deux conteneurs membres. Essayez de proposer du code C++11 et non C++11 si possible.

    C'est les vacances, prenez votre temps, fin de l'exercice à la fin du mois d'août.

  2. #2
    Membre Expert

    Avatar de germinolegrand
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2010
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2010
    Messages : 738
    Par défaut
    code C++11 et non C++11
    le 2e c'est C++03 je suppose ? ^^

  3. #3
    Membre émérite
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Par défaut
    Euh... Je suppose que cette solution est jugée comme étant une forme de triche ?

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class SafeTransaction {
       vector<int> v1, v2;
    public:
       void push_back(int x1, int x2) {
          v1.push_back(x1);
          try { v2.push_back(x2); }
          catch (...) { v1.pop_back(); throw; }
       }
    };

    Bien sûr, si pop_back() throw aussi, ça ne fonctionnera pas.
    Mais si le deuxième push_back ne fonctionne pas et que le pop_back ne veut pas s'exécuter, je suppose qu'on peut considérer que l'état du programme est suffisemment mauvais pour justifier un probable crash.

    Soit dit en passant, selon IBM (?), pop_back est nothrow. J'ai du mal à comprendre comment c'est possible sachant que le destructeur peut lancer une exception. Oui, çaymal, mais ça reste possible.

    Bref... Triche ou non ?

  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
    Tu pourrais un peu préciser ce qu'il faut respecter ?
    • Résistance fortes au exceptions (je suppose que oui) ?
    • Doit marcher en multi-thread ? Si oui sous quels conditions ?
    • Obliger d'utiliser plusieurs conteneurs ou on fait l'implémentation comme on veut tant que les services attendues (insérer plusieurs éléments en même temps) sont respectés.
    • Les éléments insérés sont liés ou non ? Par exemple le retrait d'un élément entraîne le retrait de ceux inserés avec lui ? On doit pouvoir retrouver qui a été insérer avec un élément donné ?
    • Les éléments ne peuvent s'insérer que par multitude, ou on peut insérer un élément tout seul ? Même questions pour le retrait ?
    • Quels sont les autres services typique que doit fournir la classe ? (Ca peut jouer si on est libre de faire l'implémentation comme on veut)


    Edit: Ou si tout ces paramètres sont libres, alors quel est l'utilisation typique attendue ? Savoir à quoi ca peut servir peut aider à définir ce que la classe doit faire et les différents degrés de liberté.

  5. #5
    Membre Expert

    Avatar de germinolegrand
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2010
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2010
    Messages : 738
    Par défaut
    Ekleogl : je ne pense pas que ce soit de la triche Toutefois il faudra l'étoffer.

  6. #6
    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
    @Ekleog
    Non, c'est pas de la triche, c'est très bien. C'est la méthode simple et efficace
    Par contre, tu vas être vite limité : si tu veux gérer plus de vecteurs, tu vas devoir faire des try-catch en cascade ; si tu veux pourvoir laisser à l'utilisateur la possiblité de faire les push qu'il veut (par exemple 2 dans v1 et 3 dans v2 dans une seule transaction), il faudra proposer plusieurs fonctions différentes

    @Flob90
    Trop de questions Le but est de s'amuser sur un exercice, trouver des solutions et voir quels sont les limites d'utilisation.

  7. #7
    Membre expérimenté

    Profil pro
    Inscrit en
    Mai 2005
    Messages
    264
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 264
    Par défaut
    Bonjour,

    Je viens de lire le sujet et propose une première solution "C++11" (soyez cléments, je découvre les variadic templates en C++)...

    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
     
    // Une classe generique de push_back transactionnels sur un nombre quelconque
    // de conteneurs
    // parametres:
    // - Container: une classe de conteneur (qui doit gerer push_back()/pop_back()
    // - ContainerCount: le nombre de conteneur a gerer.
    template <class Container, size_t ContainerCount>
    class SafeTransaction
    {
        // nos conteneurs internes.
        Container m_containers[ContainerCount];
     
        // Insere des elements dans des conteneurs, de maniere recursive.
        // parametres:
        // - index: index du conteneur dans le tableau m_conteneur qui va etre modifie.
        // - value: valeur a inserer
        // - values: reste des arguments...
        template<typename T, typename... Ts>
        void push_back_impl(int index, T value, Ts... values)
        {
            // A-t-on bien ajoute l'element ?
            bool done = false;
            try
            {
                // on insere l'argument en cours dans le bon conteneur
                m_containers[index].push_back(value);
                done = true;
     
                // s'il reste des arguments, on le transfere au template recursif suivant.
                if (sizeof...(values) > 0)
                {
                    push_back_impl(index+1, values...);
                }
            }
            catch (...)
            {
                // en cas d'erreur, on enleve le dernier element du conteneur et on
                // propage l'exception a l'appelant.
                if (done)
                {
                    m_containers[index].pop_back();
                }
                throw;
            }
        }
     
    public:
        // methode visible permettant d'insérer des elements dans un nombre quelconque de
        // conteneurs. Le premier argument est inséré dans le premier conteneur, le
        // deuxième argument dans le deuxieme conteneur, et ainsi de suite..
        template<typename... Ts>
        void push_back(Ts... parameters)
        {
            static_assert(sizeof...(parameters) <= ContainerCount, "Too many arguments.");
     
            if (sizeof...(parameters) > 0)
            {
                    push_back_impl(0, parameters...);
     
            }
        }
    };

Discussions similaires

  1. Exercice - Gestion des employés d'une banque
    Par Adnane-Xx dans le forum C
    Réponses: 2
    Dernier message: 03/06/2014, 17h00
  2. [sh] Exercice concaténation des lignes impaires d'un fichier
    Par ettar dans le forum Shell et commandes GNU
    Réponses: 6
    Dernier message: 29/05/2014, 13h02
  3. créer des feuilles d'exercices avec des corrigés
    Par Dexter80 dans le forum Mise en forme
    Réponses: 5
    Dernier message: 22/08/2012, 18h10
  4. exercice théorie des langages
    Par abdellah 1 dans le forum Algorithmes et structures de données
    Réponses: 1
    Dernier message: 18/04/2009, 00h14
  5. Réponses: 4
    Dernier message: 27/02/2005, 21h43

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