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 :

template de classe template


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut template de classe template
    Bonjour à tous.
    J'ai un doute si ce que je veux faire est possible.
    Mon problème est que si on a :

    template<typename T>
    class Truc;

    Alors, Truc n'est pas considéré comme un type.

    Voici mon objectif :

    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
    template<typename T>
    struct NbTemplate
    {
        static const int value=0;
    };
     
    template<template<class>class T>
    struct NbTemplate<T>
    {
        static const int value=1;
    };
     
    template<template<class,class>class T>
    struct NbTemplate<T>
    {
        static const int value=2;
    };
    //...
    Ou, plus généralement, en c++0x :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template<template<typename ...Args>class T>
    struct NbTemplate<T>
    {
        static const int value=sizeof...(Args);
    };
    Malheureusement, ce code ne compile pas car T n'est pas un type (ce qui fait qu'il n'y a aucune utilité à la classe NbTemplate et ce qui l'empêche de compiler).

    L'objectif final était d'écrire une matrice de taille connue à la compilation et qui pouvait donc prendre 2 types d'allocateurs (1 avec juste T, l'autre avec T et le nombre d'octets à allouer) sans dupliquer le code :

    J'aurais fait :

    template<typename T, unsigned Width, unsigned Height, class Allocator>
    class Matrix;

    et dedans, j'aurais fait un branchement si Allocator prend un ou deux template.

    Si vous connaissez une solution.

    Merci.

  2. #2
    Membre chevronné

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    426
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 426
    Par défaut
    Salut,
    Ne peux-tu pas tout simplement faire un patron de class avec deux constructeurs, le premier avec un seul argument T et l'autre avec T et le nombre d'octets à allouer?

  3. #3
    Membre éclairé
    Avatar de gb_68
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2006
    Messages
    232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 232
    Par défaut
    Bonjour,
    Citation Envoyé par NoIdea Voir le message
    template<typename T>
    class Truc;

    Alors, Truc n'est pas considéré comme un type.
    Mais Truc<Machin> sera un type.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    template<typename T, unsigned Width, unsigned Height, class Allocator>
    class Matrix;
    Allocator est déclaré comme type (et non template<typename T, unsigned Width, unsigned Height, template<typename> class Allocator> class Matrix; ).
    Il est possible dans ce cas détecter le nombre de paramètres templates de Allocator comme cela :
    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
    template<typename T>
    struct NbTemplate
    {
        static const int value=0;
    };
     
    template<template<class>class T, typename Arg1>
    struct NbTemplate< T<Arg1> >
    {
        static const int value=1;
    };
     
    template<template<class,class>class T, typename Arg1, typename Arg2>
    struct NbTemplate< T<Arg1,Arg2> >
    {
        static const int value=2;
    };
     
    template<template<class,size_t>class T, typename Arg1, size_t Size>
    struct NbTemplate< T<Arg1,Size> >
    { 
        // ? static const int value=2;
    };

  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
    Ce n'est pas spécialement parce que ce n'est pas un type, par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    template<class> class A;
    template<template<class> class> class B;
    template<> class B<A> {};
    Ne pose aucun problème.

    Le problème c'est que tu déclares une classe template pour un type et que tu la spécialises pour autre chose que des types, c'est comme si tu avais fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    template<class> class A;
    template<> class A<0> {};
    Code dont le fait qu'il ne compile pas ne surprendra pas grand monde ...

    Le dernier code que tu postes (en C++1x) ne marche pas pour une autre raison, ca ne sert à rien de nommer les paramètres template des TTP, ils sont inutilisable, en particulier ton Arg...

    Et enfin, même en supposant que ca puisse compiler, il y aurait un problème (en C++1x pour ce point). Imagines que tu es le compilo et que tu vois ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    template<class...> struct B;
     
    template<class T> struct B<T> {};
    template<class T, class U> struct B<T,U> {};
     
    //Puis avec ton code
    NbParam<B>::value;
    Comment tu détermines le nombre !? 1 ou 2 ?

    Sinon, voila la solution de gb_68 en C++1x (pour des paramètre templates du TTP qui ne sont que des types (*) ) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    template<class> struct NbParam;
     
    template<template<class...>class T, class... Arg>
    struct NbParam<T<Arg...> >
    { enum { value = sizeof...(Arg) }; };
    (*) Ce point peut paraitre restrictif mais ne l'est pas, car il est facile (et courrant) de transformer les constantes entières en type pour ne gérer que des types, mpl propose des outils pour ca, et il y en a aussi en C++1x.

  5. #5
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut
    Ne peux-tu pas tout simplement faire un patron de class avec deux constructeurs, le premier avec un seul argument T et l'autre avec T et le nombre d'octets à allouer?
    Merci, c'est parfait en fait : puisque la taille de la matrice est connue à la compilation, je n'ai besoin d'allouer de la mémoire qu'à la création. Problème résolut. Merci.

    Cependant, pour mes projets futurs, voici une nouvelle question :

    Soit une classe A template pouvant prendre deux types d'allocateurs :
    -un allocateur<T>
    -un allocateur<T,B>
    La classe A hérite de allocateur<...>

    Comment écrire la classe A de telle façon que l'utilisateur ne passe que allocateur et non allocateur<...> en template ?
    Est-il possible d'éviter de l'écrire en double ?

  6. #6
    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
    Je ne comprends pas trop ta question. Il suffit de faire un TTP (Template Template Paramter) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    template<template<class...> class> struct A;
    template<template<class,class> class Allocator>
    struct A<Allocator> : Allocator<?,?> {};
    template<template<class> class Allocator>
    struct A<Allocator> : Allocator<?> {};
    Après pour remplacer les ?, soit tu passes un autre paramètre template que tu inséreras à la bonne place, on gagne pas grand chose si ce n'est d'éviter la répétition de se paramètre si il y a plusieurs TTP.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    template<class T, template<class,class> class Allocator>
    struct A<Allocator> : Allocator<T,T> {};
    Sinon tu décide toi même du paramètre, mais ca sera toujours le même.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    template<class T, template<class,class> class Allocator>
    struct A<Allocator> : Allocator<int,int> {};
    Soit tu peux utiliser une classes de traits pour choisir un autre type qui dépendra soit d'un autre paramètre template soit du TTP lui-même.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    template<template<class...> class> struct TTP_Trait
    { typedef int Type; };
     
    template<template<class...> class> struct A;
    template<template<class,class> class Allocator>
    struct A<Allocator> : Allocator<typename TTP_Trait<Allocator>::Type,typename TTP_Trait<Allocator>::Type> {};
    Si par "écrire en double" tu veux dire devoir écrire les deux spécialisations, alors oui c'est possible dans certains cas : ceux où tu peux déterminer les paramètre à passer, par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    template<template<class...> class Allocator, class... Arg>
    struct A : Allocator<Arg...> {};

  7. #7
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut
    J'avais abandonné cette partie du projet un peu, pensant que c'était réglé. Cependant, je n'arrive toujours pas à trouver la solution :



    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
     
    template<typename T, unsigned L, unsigned C, bool Static, template<class> class Allocator>
    class Matrix<T,L,C,Static, Allocator> : public Allocator<T>
    {
     
    };
     
     
    template<typename T, unsigned L, unsigned C, bool Static, template<class, unsigned N> class Allocator>
    class Matrix<T,L,C,Static, Allocator> : public Allocator<T,L*C>
    {
     
    };
     
    template<typename T, unsigned Nb>
    struct MyAlloc
    {
     
    };
     
     
    using namespace std;
     
    int main()
    {
        Matrix<float, 3,3,true,MyAlloc> m;
        Matrix<float, 3,3,true,std::allocator> m;
     
        return 0;
    }
    J'ai enlevé le
    template<typename T, unsigned L, unsigned C, bool Static, template<class...> class>
    class Matrix;

    car unsigned n'est pas une classe.

    Ma question : est-il possible de faire pour que le code ci-dessus compile ?

Discussions similaires

  1. Syntaxe fonction template dans classe template
    Par Aleph69 dans le forum C++
    Réponses: 6
    Dernier message: 15/07/2011, 15h32
  2. Réponses: 4
    Dernier message: 15/10/2008, 09h33
  3. template dans un template de classe
    Par Bob.Killer dans le forum Langage
    Réponses: 1
    Dernier message: 18/12/2007, 15h44
  4. [Template] Problème Classe Template
    Par gimpycpu dans le forum Langage
    Réponses: 7
    Dernier message: 23/05/2007, 05h10
  5. Réponses: 15
    Dernier message: 21/08/2006, 01h41

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