AccueilAccueil  FAQFAQ  RechercherRechercher  Dernières imagesDernières images  S'enregistrerS'enregistrer  Connexion  
Le deal à ne pas rater :
Xiaomi Mi Smart Camera 2K Standard Edition (design compact / support ...
11.39 €
Voir le deal

 

 Python ? In my C++ ? It's more likely than you think!

Aller en bas 
AuteurMessage
Morwenn
Très bonne participation
Morwenn


Messages : 151
Projet Actuel : Icare

Python ? In my C++ ? It's more likely than you think! Empty
MessageSujet: Python ? In my C++ ? It's more likely than you think!   Python ? In my C++ ? It's more likely than you think! EmptyLun 11 Juin 2012 - 23:57

Ce soir, je m'ennuyais un peu. Et comme je dois faire du Python ces temps-ci pour une raison ou une autre et que je fais du C++ assez couramment, je me suis demandé comment faire des générateurs de manières en C++, mécanisme très présent et très élégant dans Python.

Pour parler franchement, je n'ai pas réussi à les faire de manière "générique" et transparente va-t-on dire ; j'arrivais toujours à des syntaxes assez immondes et peu compréhensibles. Donc plutôt que de m'attaquer à cette tâche un peu compliquée, je me suis dit que reprendre la fonction xrange de Python 2.x (range dans Python 3.x) qui est peut-être le générateur le plus utilisé du langage Razz
Je le rappelle pour ceux qui ne le savent pas, le principe d'un générateur est de calculer les valeurs dont on a besoin et de les renvoyer au fur et à mesure, plutôt que de tout calculer et renvoyer en une fois. On appelle ce mécanisme "évaluation paresseuse".

Afin d'avoir une syntaxe plus classe et plus Python, j'ai usé des petits avantages donnés par la nouvelle norme C++11, comme par exemple la nouvelle boucle for, directement piquée chez Java. Le but était d'obtenir la syntaxe suivante :

Code:

#include <iostream>
int main()
{
    for (int& i: range(100))
    {
        std::cout << i << std::endl;
    }
}

Donc, quand on connaît un peu le C++11, on sait que cette boucle se ramène à la syntaxe suivante :

Code:

#include <iostream>
int main()
{
    auto x = range(100);
    for (auto it = x.begin() ; it != x.end() ; ++it)
    {
        int i = *it;
        std::cout << i << std::endl;
    }
}

Ceci oblige à créer une classe range avec les fonctions suivantes :

  • range(int)
  • begin()
  • end()
  • operator++()
  • operator!=()
  • operator*()


Techniquement, ce qui va suivre est complètement dégueulasse et n'importe quel professeur ou personne un minimum sérieuse vous assassinerait probablement en voyant ça, mais toujours est-il que ça marche et que ça a bien le comportement de la fonction xrange() de Python. Voici donc l'implémentation C++ du générateur range, simplifié à l'extrême :

Code:

class range
{
    private:

        const int _val; // Valeur finale
        int _i;    // Valeur courante

    public:

        range(int val):
            _val(val),
            _i(0)
        {}

        range& begin()
        {
            return *this;
        }

        range& end()
        {
            return *this;
        }

        bool operator!=(const range&)
        {
            return _i != _val;
        }

        void operator++()
        {
            ++_i;
        }

        int operator*()
        {
            return _i;
        }
};

Comme vous pouvez le voir, rien de bien compliqué. Seulement, on notera que l'objet en lui-même agit à la manière d'un itérateur, comme ceux de la bibliothèque standard. Notez aussi, qu'on n'a absolument rien à faire des valeurs de end() dans l'opérateur de différence et qu'on lui fait donc toujours retourner la même chose que begin(). Comment ça c'est moche ?

Quitte à être sale, autant rajouter une petite macro pour avoir un résultat encore plus Python, non ?
Code:

#define in :

J'ai dû vous exposer un plus gros pourcentage de code C++ sale en quelques lignes que vous n'aurez l'occasion d'en voir tant que vous n'utiliserez pas de templates pour faire de la métaprogrammation comme des barbares. Mais quel est donc le plaisir quand enfin on peut écrire ceci de manière complètement légale et fonctionnelle^^

Code:

int main()
{
    for (int& i in range(100))
    {
        std::cout << i << std::endl;
        if (i == 30) break;
    }
}

_________________
Python ? In my C++ ? It's more likely than you think! 37115040594310152086589335317875357842n
Dur Dabla, pour qui voudrait écouter un brin de metal celtique.
Revenir en haut Aller en bas
 
Python ? In my C++ ? It's more likely than you think!
Revenir en haut 
Page 1 sur 1

Permission de ce forum:Vous ne pouvez pas répondre aux sujets dans ce forum
Forum Le CBNA :: Développement :: Programmation-
Sauter vers: