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 :

Déroulé de boucle via un template


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Février 2003
    Messages
    44
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Février 2003
    Messages : 44
    Points : 49
    Points
    49
    Par défaut Déroulé de boucle via un template
    Bonjour à tous !

    J'utilise depuis longtemps dans un de mes programme des fonctions permettant de lire le contenu d'un std::array de uint8_t. J'ai 3 fonctions génériques permettant de retourner soit un uint8_t, soit un uint16_t, soit un uint32_t.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    template<typename U, ::std::size_t N>
    uint8_t RawRead8(const ::std::array<U, N> & arr, const ::std::uint32_t& adr)
    {
        return arr[adr];
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    template<typename U, ::std::size_t N>
    uint16_t RawRead16(const ::std::array<U, N> & arr, const ::std::uint32_t& adr)
    {
        return arr[adr + 0] << 8 | arr[adr + 1];            
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    template<typename U, ::std::size_t N>
    uint32_t RawRead32(const ::std::array<U, N> & arr, const ::std::uint32_t& adr)
    {
        return arr[adr + 0] << 24 | arr[adr + 1] << 16 | arr[adr + 2] << 8 | arr[adr + 3];
    }
    Rien de bien folichon donc, mais ça oblige à créer autant de fonctions que de type de retour ...

    J'ai donc voulu créer une unique fonction permettant de gérer autant de types que voulu (par ex retourner aussi un uint64_t).
    Voici le résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    template<typename T, typename U, ::std::size_t N>
    decltype(auto) RawRead(const ::std::array<U, N> & arr, const ::std::uint32_t& adr)
    {
        T returnValue{};
        for (uint8_t i = 0; i <= sizeof(T) - 1; ++i) {
            returnValue <<= 8;
            returnValue |= arr[adr + i];
     
        }
        return returnValue;
    }
    Et un exemple d'utilisation:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    std::array <uint8_t, 0x100> memory;
    memory[0] = 0xFE;
    memory[1] = 0xDC;
    memory[2] = 0xBA;
    memory[3] = 0x98;
     
    auto val32 = RawRead<uint32_t>(memory, 0x0);
    Ce code fonctionne parfaitement. Mais lors de la vérification du code assembleur généré, je me rends compte que cette dernière fonction génère le code correspondant à la boucle, au lieu de faire une série de décalage à gauche comme la première fonction
    Existe-t-il un moyen pour forcer le compilateur à dérouler la boucle ? Je ne suis pas assez calé en templates pour avoir la solution (je ne suis même pas sûr que ce soit faisable).

    Merci de m'avoir lu

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Oui, bien sur, qu'il y a moyen... il faut juste réfléchir "un tout petit peu"

    Par exemple, n'as tu pas remarqué que la génération d'un uint32_t revient à générer deux uint16_t et à appliquer un décalage de bits sur l'un d'eux
    Tu pourrais donc envisager de créer ton uint32_t sous une forme qui serait proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return static_cast<uint32_t>(RawRead16(arr[0])<<16 + rawRead16(arr[2]);
    Ceci étant dit, il faut comprendre que le compilateur dispose de certains algorithmes qui lui permettent de déterminer s'il est plus intéressant de dérouler une boucle ou, au contraire, de créer une boucle sur base des manipulations qui sont effectuées. De manière générale, tu peux estimer que, si ces algorithmes ont fait que le compilateur a décidé de créer une boucle, c'est parce qu'il estimait (sur base de ses réglages actuels) que c'était la solution la plus adaptée. Et tu peux lui faire confiance sur ce coup

    Avec Gcc, par exemple, on dispose d'un bon nombre d'options qui permettent de choisir la manière dont le code binaire sera généré. Le simple fait de passer d'une option -O à une option -O1 / -O2 / -O3 / -Os ou -Ofast aura très certainement une influence sur le choix effectué dans cette situation
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. Optimisation de boucles via calcul matriciel
    Par HAL-9000 dans le forum MATLAB
    Réponses: 12
    Dernier message: 06/03/2010, 21h53
  2. comment récupérer un element dans un listbox via un template d'element
    Par Pol63 dans le forum Windows Presentation Foundation
    Réponses: 16
    Dernier message: 28/04/2009, 23h17
  3. [MySQL] Récuperation de données dans un boucle via une requête PHP
    Par bodysplash007 dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 19/04/2007, 11h39
  4. simuler le polymorphisme via les templates
    Par ronaldino dans le forum C++
    Réponses: 10
    Dernier message: 28/11/2006, 00h15
  5. [vb6] Lecture en boucle via port COM
    Par Original Prankster dans le forum VB 6 et antérieur
    Réponses: 1
    Dernier message: 25/10/2006, 21h34

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