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++

  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 : 35
    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...);
     
            }
        }
    };

  8. #8
    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
    Y'a un truc que je capte pas dans le code Ekleog. Si v1.push_back lance une exception, il n'a aucun moyen de la rattraper � l'int�rieur de la fonction. Et donc son code n'est pas transactionnel.

    Ou j'ai loup� un truc.
    "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)

  9. #9
    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
    @davidbrcz: si justement, si v1 throw, alors v1 et v2 restent dans le m�me �tat qu'au d�but de la fonction.
    edit: disons que ce n'est qu'une partie sous-jacente d'une transaction qui est demand�e ici.

  10. #10
    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
    Voil� pour des general-purpose transactions :
    Code cpp : 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
    #include <functional>
    #include <vector>
     
    using action_cb   = std::function<void ()>;
    using rollback_cb = std::function<void ()>;
     
    struct Transaction {
       action_cb    action;
       rollback_cb  rollback;
       Transaction* next;
     
       void execute() {
          action();
          if (next) {
             try {
                next->execute();
             } catch (...) {
                rollback();
                throw;
             }
          }
       }
    };
     
    void transaction(std::vector<std::pair<action_cb, rollback_cb>> const & actions) {
       // Build transaction array and linked-list
       std::vector<Transaction> transactions(actions.size());
       for (std::size_t i = 0 ; i < actions.size() ; ++i) {
          transactions[i].action   = actions[i].first;
          transactions[i].rollback = actions[i].second;
          transactions[i].next     = &transactions[i + 1];
       }
       // Fix last pointer
       transactions[actions.size() - 1].next = nullptr;
       // Execute
       transactions[0].execute();
    }
     
    #include <iostream>
     
    int main() {
       try {
          transaction({
             { [] () { std::cout << "Running transaction\n"; },
               [] () { std::cout << "Rollbacked transaction\n"; }
             },
             { [] () { new int [999999999999999]; std::cout << "Unreachable.\n"; },
               [] () { std::cout << "Should never be called !\n"; }
             }
          });
       } catch (std::exception const & e) {
          std::cerr << "Exception caught : " << e.what() << " ; ignoring...\n";
       }
     
       std::vector<int> v1, v2, v3;
       transaction({
          { [&v1] () { v1.push_back(1); },
            [&v1] () { v1.pop_back(); }
          },
          { [&v2] () { v2.push_back(2); },
            [&v2] () { v2.pop_back(); }
          },
          { [&v3] () { v3.push_back(3); },
            [&v3] () { v3.pop_back(); }
          }
       });
       // Mériterait probablement un wrapper, mais ici c'est une transaction
       // générique, pas seulement orientée push_back !
     
       for (int i : v1) std::cout << i << " ";
       for (int i : v2) std::cout << i << " ";
       for (int i : v3) std::cout << i << " ";
       std::cout << "\n";
    }

    Alors, vous en pensez quoi ? (Note : chez moi, new int [999999999999999]; lance une out_of_memory. Je trouvais moche de simplement faire un throw, en fait. Sinon, vous pouvez remplacer par n'importe quel throw, en fait.)

    [Edit suite � la lecture de Davidbrcz: Pour moi, il faut soit que tout fonctionne, soit que rien ne change et que l'exception soit remont�e � l'appellant (potentiellement, si on utilise boost::exception, avec ajout d'informations sur le site sp�cifique de l'erreur). Est-ce que j'ai mal compris le sujet ?]

    [Edit2: Ajout� � ma liste d'utilitaires divers et vari�s dont je ne me suis encore jamais servi : https://github.com/Ekleog/misc/blob/master/transaction.cpp ]

    [Edit3: OMG l'horreur que j'ai �crit ! Piti�, dites moi que vous n'avez pas eu le temps de lire le code o� j'avais laiss� les new/delete tr�s mal g�r�s.]

  11. #11
    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
    Citation Envoy� par Ekleog Voir le message
    [Edit suite � la lecture de Davidbrcz: Pour moi, il faut soit que tout fonctionne, soit que rien ne change et que l'exception soit remont�e � l'appellant (potentiellement, si on utilise boost::exception, avec ajout d'informations sur le site sp�cifique de l'erreur). Est-ce que j'ai mal compris le sujet ?]
    Non non, tu as bien un transaction : tout est commit ou rien ne l'ai. L'utilisateur de ton code sait que si une exception survient, c'est que aucun vector n'a �t� modifi�. Libre � lui ensuite de refaire le push complet ou autre chose

    EDIT : pour r�pondre � une question de germinolegrand, pour tester si un param�tre est bien un conteneur : boost::spirit is_container
    Peux aider pour avoir des messages d'erreurs template user-friendly...

  12. #12
    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
    germinolegrand >> Ouais ouais. J'avais juste mal lu le premier post. Dans ma t�te, fallait �tre capable de continuer m�me si l'une plantait.

    Mais � r�fl�chir, c'est d�j� le cas, suffit d'attraper l'exception qui en sort.
    "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)

  13. #13
    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
    Citation Envoy� par Davidbrcz Voir le message
    Mais � r�fl�chir, c'est d�j� le cas, suffit d'attraper l'exception qui en sort.
    Oui bien sur, on peut catcher l'exception pour savoir quel push_back � planter et l'annuler ou le refaire. C'est ce que fait Ekleog.

    Mais c'est alors la responsabilit� de l'utilisateur de le faire, ce qui revient � dire que �a peut ne pas �tre fait.

    L�, l'id�e est de dire que la responsabilit� de l'int�grit� de la transaction est une responsabilit� � part enti�re, qui doit donc �tre prise en charge par une structure sp�cifique et pas laiss�e � la bonne volont� de l'utilisateur.

  14. #14
    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
    Niark13> Je crois que, ligne 32, ce devrait plut�t �tre push_back_impl. Non ?

    Sinon, aucun commentaire sur les quelques propositions d�j� avanc�es ?

  15. #15
    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 : 35
    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
    Les codes propos�s utilisent pour le moment tous le m�me m�chanisme (en r�cursif et en it�ratif). La version it�rative utilisant en plus un pattern Command.

    Pour la version r�cursive, il est �trange de terminer la r�cursion avec un if alors que tout est connu � la compilation. On aurait pu la terminer en utilisant une surcharge avec un PP vide (ie pas de PP) pour push_back_impl. Le test de la positivit� de la taille du PP est aussi �trange, elle est n�cessairement positive et le cas nul devrait pouvoir �tre le cas terminal.

    Les deux solutions, �tant bas�es sur le m�me m�canisme, ne sont pas thread-safe. Si deux transactions sont faites en m�me temps sur les m�me conteneurs, alors si tout se passe bien rien ne garantit que l'ordre des �l�ments soit celui d'un des deux cas s�quentiel associ�, et si l'un des deux lance une exception, l'�tat peut devenir invalide.

  16. #16
    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 : 51
    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
    Par d�faut
    Dans la version du code pr�sent� initialement, avec un objet contenu ne lan�ant pas d'exception � la copie, je ferais simplement :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    void push_back(int x1, int x2) { 
     
          v1.reserve(v1.size()+1);
          v2.reserve(v2.size()+1);
          v1.push_back(x1);
          v2.push_back(x2);
       }
    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.

  17. #17
    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
    J'aime les solutions simples

    Par contre, ton code est sp�cifique � vector

  18. #18
    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 : 51
    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
    Par d�faut
    En effet. Par contre, si on veut �tre plus g�n�rique, il va falloir pr�ciser un peu tout de m�me (m�me si je comprends l'aspect ludique du probl�me, ce n'est pas �vident d'y r�fl�chir si le cadre est trop flou)...

    D�j�, c�t� conteneur, je suppose, vu l'�nonc�, qu'il faut que �a marche pour toutes les s�quences fournissant push_back ? Et comme dans le standard, elles fournissent aussi pop_back, il me semble raisonnable de supposer que l'on a aussi droit � �a (plus tout le reste de ce qui d�fini une s�quence).

    Maintenant, c�t� objet contenu, il y a d'autres questions qui se posent, � la r�ponse moins tranch�e...
    Le type est-il suppos� r�gulier (en particulier, CopyConstructible et CopyAssignable) ?
    Quelles sont les fonctions que l'on peut supposer noexcept(true) ? Le destructeur (sinon, c'est vraiment difficile de raisonner, et c'est impos� par le standard pour avoir le droit de mettre un objet dans un conteneur (ce qui r�pond � la question d'Ekleog sur pop_back)). Mais y en a-t-il d'autres ? le move constructor ? swap ?

    Une solution qui marche avec les types r�guliers (mais pas forc�ment optimale en terme de performances, c'est le moins qu'on puisse dire), et quel que soit le conteneur :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    Cont1 copy1 = cont1;
    Cont2 copy2 = cont2;
    copy1.push_back(x1);
    copy2.push_back(x2);
    copy1.swap(cont1);
    copy2.swap(cont2);
    Rem : On peut optimiser un peu en ne faisant pas de copie pour le dernier conteneur.
    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.

  19. #19
    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
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    Cont1 copy1 = cont1;
    Cont2 copy2 = cont2;
    copy1.push_back(x1);
    copy2.push_back(x2);
    copy1.swap(cont1);
    copy2.swap(cont2);
    Oh la brute

    Pour pusk_back et pop_back, comme tu veux. Mais par exemple map n'a pas ces fonctions. insert et erase est plus g�n�rique. L'id�al est peut �tre de pouvoir param�trer ? (mais �a alourdi)

    type r�gulier ? a priori, oui. Il faut au mois que le type passe dans un conteneur, tu penses � un conteneur particulier qui accepterait des types non r�guliers ?

    A priori, oui, pop_back, erase, move constructeur, swap sont noexept. Je sais pas si cette propri�t� est indiqu� dans une r�f�rence ?

  20. #20
    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
    Allez, en r�utilisant ma fonction transaction d�j� post�e, un helper pour push_back (non test�, et il doit y avoir un meilleur moyen pour alterner non const et const... tout comme il doit y avoir un meilleur moyen pour faire tout ce bout de code, en fait.) :
    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
    template <class C, typename T, typename... Args>
    std::list<std::pair<action_cb, rollback_cb>> pb_trans_impl_impl(C & cont, T const & val, Args &... args) {
       auto sub = pb_trans_impl_impl(args...);
       sub.push_front({ [&cont, &val] () { cont.push_back(val); },
                        [&cont]       () { cont.pop_back(); }
                      });
       return sub;
    }
     
    template <>
    std::list<std::pair<action_cb, rollback_cb>> pb_trans_impl_impl() {
       return {};
    }
     
    template <typename... Args>
    std::vector<std::pair<action_cb, rollback_cb>> pb_trans_impl(Args &... args) {
       auto list = pb_trans_impl_impl(args...);
       return std::vector<std::pair<action_cb, rollback_cb>>(list.begin(), list.end());
    }
     
    template <typename... Args>
    void pb_trans(Args &... args) {
       transaction(pb_trans_impl(args...));
    }
     
    // ...
    int main() {
       std::vector<int> vi;
       std::vector<double> vd;
       std::vector<float> vf;
       pb_trans(vi, 42, vd, 3.14, vf, 1.f);
    }
    (Ca me fait penser que j'aurais d� rendre ma fonction transaction ind�pendante du type de conteneur...)

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