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

Langage C++ Discussion :

Blocage sur un template


Sujet :

Langage C++

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 19
    Par défaut Blocage sur un template
    Bonjour,

    J'ai un petit type enum (en C) qui liste les formats vidéo possibles :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    typedef enum video_pixelFormat {
    	VIDEO_PIXELFORMAT_8BITSPALETTE,
    	VIDEO_PIXELFORMAT_R5G5B5,
    	VIDEO_PIXELFORMAT_R5G6B5,
    	VIDEO_PIXELFORMAT_R8G8B8,
    	VIDEO_PIXELFORMAT_R8G8B8A8
    } video_pixelFormat;

    Et là je suis en train d'essayer de créer une template classe "Color" qui prendrait comme paramètre de template l'un de ces formats.

    En gros ce que je veux faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Color<VIDEO_PIXELFORMAT_R5G5B5> couleur(255, 190, 0);
    *memoireVideo = couleur;

    Mais j'essaye en long en large et en travers, j'arrive pas à compiler ce foutu truc :-/

    Mon problème vient de la détermination du nombre d'octets formant un pixel.

    J'ai d'abord essayé ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    template<video_pixelFormat TFormat>
    class Color {
    	static const int BytesPerPixel = 0;
    	unsigned char _data[BytesPerPixel];
    };
     
    template<>
    const int Color<VIDEO_PIXELFORMAT_R5G6B5>::BytesPerPixel = 2;
    Résultat : erreur: duplicate initialization of ‘Color<VIDEO_PIXELFORMAT_R5G6B5>::BytesPerPixel’

    Si j'enlève le "=0" il ne veut pas créer le tableau _data : erreur: array bound is not an integer constant.


    J'ai donc essayé de créer une template struct à l'intérieur de ma template class :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    template<video_pixelFormat TFormat>
    class Color {
    	template<video_pixelFormat TFormat2> struct DataSize { static const int Size = 0; };
    	template<> struct DataSize<VIDEO_PIXELFORMAT_R5G6B5> { static const int Size = 2; }
     
    	static const int BytesPerPixel = DataSize<TFormat>::Size;
    	unsigned char _data[BytesPerPixel];
    };
    Mais erreur à la ligne qui commence par "template<>" : erreur: explicit specialization in non-namespace scope ‘class Color<TFormat>’

    J'ai donc essayé de sortir ce truc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    template<video_pixelFormat TFormat>
    class Color {
    	template<video_pixelFormat TFormat2> struct DataSize { static const int Size = 0; };
     
    	static const int BytesPerPixel = DataSize<TFormat>::Size;
    	unsigned char _data[BytesPerPixel];
    };
     
    template<>
    template<>
    struct Color<VIDEO_PIXELFORMAT_R5G6B5>::DataSize<VIDEO_PIXELFORMAT_R5G6B5> { static const int Size = 2; }
    (à noter que j'ai essayé des dizaines de combinaisons pour le truc en dehors avant d'en arriver là)

    Mais : erreur: redefinition of ‘struct Color<VIDEO_PIXELFORMAT_R5G6B5>:ataSize<VIDEO_PIXELFORMAT_R5G6B5>’


    Et là je commence à faire une overdose... pas moyen de faire comprendre à ce foutu compilateur ce que je veux...

    Donc si un expert en templates pouvait me donner un petit coup de mains, ce serait sympa


    EDIT : je sais qu'en sortant "DataSize" de "Color" ça va très certainement marcher, mais cette solution ça ressemble à du système D ; au delà du fait que ça fonctionne je voudrais un truc propre

  2. #2
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut
    Ben il me semble que la définition d'un template commence toujours parou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    template<typename Type>
    . Dans ton code je vois déjà
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    template<video_pixelFormat TFormat>
    Il vient d'où video_pixelFormat à cet endroit ?
    Ou alors il y a une subtilité de syntaxe que j'ignore.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 19
    Par défaut
    Citation Envoyé par camboui Voir le message
    Il vient d'où video_pixelFormat à cet endroit ?
    De l'enum

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    typedef enum video_pixelFormat {
    	VIDEO_PIXELFORMAT_8BITSPALETTE,
    	VIDEO_PIXELFORMAT_R5G5B5,
    	VIDEO_PIXELFORMAT_R5G6B5,
    	VIDEO_PIXELFORMAT_R8G8B8,
    	VIDEO_PIXELFORMAT_R8G8B8A8
    } video_pixelFormat;

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Mars 2009
    Messages : 31
    Par défaut
    Bonsoir,

    Pourquoi ne pas faire une classe générique avec le nombre d'octets en paramètres et ensuite une classe dérivée pour chaque format ?
    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
     
    typedef enum video_pixelFormat {
            VIDEO_PIXELFORMAT_8BITSPALETTE,
            VIDEO_PIXELFORMAT_R5G5B5,
            VIDEO_PIXELFORMAT_R5G6B5,
            VIDEO_PIXELFORMAT_R8G8B8,
            VIDEO_PIXELFORMAT_R8G8B8A8
    } video_pixelFormat;
     
    template<int bytesPerPixel>
    class ColorBytes {
            static const int BytesPerPixel = bytesPerPixel;
            unsigned char _date[bytesPerPixel];};
     
    class Color8bitsPalette : public ColorBytes<1> {
            // etc.
    };
    class ColorR5G6B5 : public ColorBytes<2> {
            // etc.
    };

  5. #5
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    De mémoire, tu ne peux pas utiliser un enum comme paramètre de template. Par contre, tu peux tout à fait utiliser un int, et profiter des conversions int <-> enum.

  6. #6
    Membre chevronné
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    349
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : Suisse

    Informations forums :
    Inscription : Novembre 2005
    Messages : 349
    Par défaut
    Un enum ne déclare pas un noueau type comme le fait une classe.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    enum {LUNDI, MARDI, MERCREDI}
    c'est comme faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #define LUNDI 0
    #define MARDI 1
    #define MERCREDI 2

  7. #7
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    Non, c'est loin d'être équivalent. Un enum définit bien un nouveau type.

    Essaie de compiler le code suivant pour t'en convaincre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    enum toto { A, B, C };
    enum titi { D, E, F };
    int main()
    {
            toto a = E;
            return 0;
    }

  8. #8
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Bonjour,
    On peut très bien utiliser un enum comme paramètre template. Tu es parti sur la bonne solution. La seule chose, c'est que tu mélange 2 infos dans ta classe et je pense qu'il faut simplement que tu sépares en 2 :
    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
     
    // pas besoin de typedef en c++
    enum video_pixelFormat {
    	VIDEO_PIXELFORMAT_8BITSPALETTE,
    	VIDEO_PIXELFORMAT_R5G5B5,
    	VIDEO_PIXELFORMAT_R5G6B5,
    	VIDEO_PIXELFORMAT_R8G8B8,
    	VIDEO_PIXELFORMAT_R8G8B8A8
    };
     
     
    template<video_pixelFormat TFormat> struct ColorDepth{};
     
    template<>
    struct ColorDepth<VIDEO_PIXELFORMAT_R5G6B5>{
       static const int BytesPerPixel = 2;
    };
     
    template<video_pixelFormat TFormat>
    struct Color {
     
       unsigned char _data[ColorDepth<TFormat>::BytesPerPixel];
    };
     
     
     
    int main()
    {
       Color <VIDEO_PIXELFORMAT_R5G6B5> rgb;
    ...
       return 0;
    }
    [EDIT] Ze bible (lanorme):
    A template-argument for a non-type, non-template template-parameter shall be one of:
    — an integral constant-expression of integral or enumeration type; or
    — the name of a non-type template-parameter; or
    — the address of an object or function with external linkage, including function templates and function
    template-ids but excluding non-static class members, expressed as & id-expression where the & is
    optional if the name refers to a function or array, or if the corresponding template-parameter is a reference;
    or
    — a pointer to member expressed as described in 5.3.1 .

  9. #9
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    Effectivement, on peut utiliser un enum.

    Mon souvenir de passer par des int vient du fait que j'avais fait des choses du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    enum toto { A = 1, B = 2, C = 4 };
    ...
     
    ma_class<A | C>
    Qui nécessitent que le template soit défini sur int, et de jouer ensuite avec les casts dans tous les sens côté implémentation du template (en gros, il y avait pas mal de cas conditionnels qui du coup étaient résolus à la compilation).

  10. #10
    Membre chevronné
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    349
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : Suisse

    Informations forums :
    Inscription : Novembre 2005
    Messages : 349
    Par défaut
    Ok j'ai appris quelque chose

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 19
    Par défaut
    Rebonjour et merci de vos réponses,

    Citation Envoyé par 3DArchi Voir le message
    Tu es parti sur la bonne solution. La seule chose, c'est que tu mélange 2 infos dans ta classe et je pense qu'il faut simplement que tu sépares en 2 :
    Donc il n'est pas possible de tout regrouper en une seule classe ? :o

    Ce qui est bizarre c'est qu'apparemment mon idée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    template<video_pixelFormat TFormat>
    class Color {
    	template<video_pixelFormat TFormat2> struct DataSize { static const int Size = 0; };
    	template<> struct DataSize<VIDEO_PIXELFORMAT_R5G6B5> { static const int Size = 2; }
     
    	static const int BytesPerPixel = DataSize<TFormat>::Size;
    	unsigned char _data[BytesPerPixel];
    };
    Ca compile sous Visual C++ mais pas sous GCC
    erreur: explicit specialization in non-namespace scope ‘class Color<TFormat>’
    Serait-ce un bug de g++ ?
    A priori les lignes 3 et 4 (de ce que j'ai copié collé) sont dans le même namespace donc je vois pas pourquoi il me met cette erreur
    ...ou alors je comprends mal l'erreur

  12. #12
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    Tu dois mettre ta spécialisation dans le .cpp, pas le .h, non ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    template<> struct DataSize<VIDEO_PIXELFORMAT_R5G6B5> { static const int Size = 2;
    cette ligne, à déplacer dans le .cpp

  13. #13
    Membre averti
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 19
    Par défaut
    Citation Envoyé par white_tentacle Voir le message
    Tu dois mettre ta spécialisation dans le .cpp, pas le .h, non ?
    Nonon elle est bien dans le .h et tout

    Je comprends le principe d'un template et pour moi leur fonctionnement parait logique, mais dans ce cas là je comprends pas pourquoi ça ne marche pas

  14. #14
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    J'ai dit une petite connerie vendredi dernier (et en plus, je n'étais pas clair ). Tu dois mettre ta spécialisation dans le .h, pour qu'elle soit visible partout.

    Par contre, tu dois la sortir de ta classe. C'était ça que je voulais dire.

    Donc, écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    template<> struct Color::DataSize<VIDEO_PIXELFORMAT_R5G6B5> { static const int Size = 2; }
    En dehors de la classe.

  15. #15
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par white_tentacle Voir le message
    J'ai dit une petite connerie vendredi dernier (et en plus, je n'étais pas clair ). Tu dois mettre ta spécialisation dans le .h, pour qu'elle soit visible partout.

    Par contre, tu dois la sortir de ta classe. C'était ça que je voulais dire.
    Donc, écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    template<> struct Color::DataSize<VIDEO_PIXELFORMAT_R5G6B5> { static const int Size = 2; }
    En dehors de la classe.
    Ca compile pas
    Citation Envoyé par Tomaka17 Voir le message
    Donc il n'est pas possible de tout regrouper en une seule classe ? :o
    Je pense que c'est typiquement le cas où tu devrais séparer les 2. Quels sens donnes-tu sinon à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Color<VIDEO_PIXELFORMAT_R5G6B5>::DataSize<VIDEO_PIXELFORMAT_8BITSPALETTE>::Size
    rendu possible avec ton code ?
    Citation Envoyé par Tomaka17 Voir le message
    Ce qui est bizarre c'est qu'apparemment mon idée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    template<video_pixelFormat TFormat>
    class Color {
    	template<video_pixelFormat TFormat2> struct DataSize { static const int Size = 0; };
    	template<> struct DataSize<VIDEO_PIXELFORMAT_R5G6B5> { static const int Size = 2; }
     
    	static const int BytesPerPixel = DataSize<TFormat>::Size;
    	unsigned char _data[BytesPerPixel];
    };
    Ca compile sous Visual C++ mais pas sous GCC
    Serait-ce un bug de g++ ?
    En général gcc est plus conforme de la norme que visual. Donc j'aurais tendance à penser qu'il s'agit d'une libéralité de Visual.

  16. #16
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    Ca compile pas
    Hmm... Ça doit être parce que Color est elle-même une classe template...

    Du coup, je ne suis pas sûr que tu puisses spécialiser Datasize pour tout Color... (en tout cas, je ne sais pas l'exprimer en C++ ).

  17. #17
    Membre averti
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 19
    Par défaut
    Bon ben j'ai séparé le schmilblick en deux

    Avec un truc de ce genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    template<> struct ColorFormatInfos<VIDEO_PIXELFORMAT_R8G8B8> {
    	static const int BytesPerPixel = 3;
     
    	static const int RedMask = 0xff;
    	static const int RedShift = 16;
    	static const int GreenMask = 0xff;
    	static const int GreenShift = 8;
    	static const int BlueMask = 0xff;
    	static const int BlueShift = 0;
    	static const int AlphaMask = 0x0;
    	static const int AlphaShift = 0;
    };
    Et du coup ma classe Color n'a même plus besoin de spécialisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    void _setColor(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha) {
    #pragma warning(push)
    #pragma warning(disable:4293)
    	unsigned int value =	((red & ColorFormatInfos<TFormat>::RedMask) << ColorFormatInfos<TFormat>::RedShift) |
    				((green & ColorFormatInfos<TFormat>::GreenMask) << ColorFormatInfos<TFormat>::GreenShift) |
    					(ColorFormatInfos<TFormat>::BlueShift >= 0 ?
    					((blue & ColorFormatInfos<TFormat>::BlueMask) << ColorFormatInfos<TFormat>::BlueShift) :
    					((blue & ColorFormatInfos<TFormat>::BlueMask) >> -ColorFormatInfos<TFormat>::BlueShift)) |
    				((alpha & ColorFormatInfos<TFormat>::AlphaMask) << ColorFormatInfos<TFormat>::AlphaShift);
    #pragma warning(pop)
    	memcpy(_value, &value, ColorFormatInfos<TFormat>::BytesPerPixel);
    }
     
    unsigned char _value[ColorFormatInfos<TFormat>::BytesPerPixel];
    En tout cas ça marche (même si j'aurais préféré tout mettre en une seule classe parce que les données de ColorFormatInfos c'est un peu des trucs internes)

    Je n'ai pas encore pû tester mon code final avec g++ (j'ai pas de PC avec Linux sous la main) mais a priori il ne devrait pas râler (j'avais déjà testé une ébauche de ce truc)



    Question subsidiaire () : actuellement ma classe Color est une 'Plain Old Data Structure' dans Visual C++ (c-à-d compatible avec une structure C du même type) ce qui me permet de faire des 'memcpy' depuis un tableau de Color<...> vers un frame buffer vidéo

    Mais y a-t-il un moyen de savoir si c'est le cas avec tous les compilateurs ? (à part les tester un par un en compilant et en voyant si ça marche)
    Parce que les conditions requises pour que ce soit une PODS ont l'air assez bizarres

Discussions similaires

  1. Blocage sur récursivité de base
    Par gilles641 dans le forum Algorithmes et structures de données
    Réponses: 1
    Dernier message: 07/04/2006, 13h42
  2. blocage sur Left
    Par TSS dans le forum Access
    Réponses: 5
    Dernier message: 10/03/2006, 12h33
  3. [10g1][OCI][C++][IIS] Blocage sur un update
    Par Herode dans le forum Interfaces de programmation
    Réponses: 2
    Dernier message: 21/02/2006, 09h32
  4. [XSL] Prob. de tri sur un template
    Par Trin dans le forum XSL/XSLT/XPATH
    Réponses: 1
    Dernier message: 16/11/2005, 11h47

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