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 :

template et type_traits


Sujet :

Langage C++

  1. #1
    Membre expérimenté Avatar de davcha
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 258
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 258
    Points : 1 539
    Points
    1 539
    Par défaut template et type_traits
    Bonjour,

    Cette fois, j'aimerais éviter de créer 12000 templates pour tous les types de données arithmétiques possibles. Aussi, j'arrive avec ce bout de code (qui ne marche pas) :

    Code c++ : 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
    #include <type_traits>
    #include <iostream>
     
    using namespace std;
     
    template<class T>
    inline int f(const T& t){
    	if(is_class<T>::value){
    		return 1337;
    	}else if(is_arithmetic<T>::value){
    		cout << t+1;
    		return 9999;
    	}
    }
     
    class A{
    public:
    	A(){}
    };
     
    int main(){
    	A a;
    	cout << f(a);
    	cout << f(3);
    	cout << f(0.5);
    	return 0;
    }

    Je pense que vous voyez ce que je cherche à faire. Le but est d'éviter des constructions comme :
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    template<>int f(const float& t)...
    template<>int f(const int& t)...
    //etc...

  2. #2
    En attente de confirmation mail

    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 : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Bonjour,

    Il faut éviter de mélanger les structures de méta-programmation et celles de programmation impérative lorsque tout est déterminable à la compilation. Le compilateur peut en effet optimiser dans certains cas, mais l'utilisation uniquement de structures de méta-programmation assure que ceci sera nécessairement fait à la compilation.

    Dans ton cas, regardes du côté de std::conditional dans le header type_traits. Après selon le degré de méta-prog que tu veux utiliser, boost::mpl sera peut-être plus désigné.

  3. #3
    Membre expérimenté Avatar de davcha
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 258
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 258
    Points : 1 539
    Points
    1 539
    Par défaut
    Je ne connaissais pas mpl ou conditional. Ceci dit, c'est pas trop mon problème ici.
    J'avais implementé au départ un template permettant de faire des test conditionels et de lancer une fonction au besoin.

    Mon souci vient plutôt du fait que j'ai un template avec un paramètre, disons T.
    Et que ce paramètre peut soit être une classe, soit un type arithmétique.
    Dans chaque cas, j'effectue des opérations qui ne sont pas possible dans l'autre cas.

    Dans l'exemple donné, j'effectue une addition, par exemple.

  4. #4
    En attente de confirmation mail

    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 : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    J'avais bien compris ton problème, et il vient bien du fait que tu fais des sélections conditionnels à l’exécution sur des choses déterminées à la compilation. Du coup si le code de chaque "branches conditionnelles" ne peut pas être "résolue" dans tout les cas le compilateur refuse.

    Il faut utiliser les mécanismes de sélection conditionnelle à la compilation pour résoudre ton problème. Si tu as du code à évaluer à l’exécution dans tes branches, il faut coupler ceci à un autre mécanisme pour arriver à quelque chose de fonctionnel :

    Un de ces mécanisme est le tag dispatching. Pour résumer l'idée, tu crées des dummy type correspondant à tes différents cas, ensuite tu crées des fonctions de la forme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    template<class T>
    void foo_impl(/*...*/, const Dumme1&)
    { /*code cas 1*/ }
    Pour chacun de tes cas, et tu fais quelque chose de la forme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    template<class T>
    void foo(/*...*/)
    { 
      typedef typename tmp_algo<T>::type type;
      foo_impl(/*...*/, type());
    }
    Ou tmp_algo est un algorithme de méta-programmation permettant de choisir le dummy type correspondant au T (basiquement c'est un trait, et en poussant un algorithme) : c'est lui qui utilisera std::conditional / boost::mpl.

    Une autre solution possible est d'écrire les différents cas sous forme de foncteurs polymorphiques et de faire sélectionner à l'algoritme de méta-programmation l'un de ces foncteurs, et ensuite de l'instancier et de "l'appeler". Cependant, je partirais sur le tag dispatching, qui me semble plus simple dans ce cas là.

  5. #5
    Membre expérimenté Avatar de davcha
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 258
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 258
    Points : 1 539
    Points
    1 539
    Par défaut
    Merci, j'ai trouvé mon bonheur.

  6. #6
    Membre expérimenté Avatar de davcha
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 258
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 258
    Points : 1 539
    Points
    1 539
    Par défaut
    J'ai parlé trop vite, c'est un peu plus compliqué que ça encore, en fait.
    Le problème est que je surcharge des opérateurs qui, forcément, retournent des valeurs.

    Exemple :
    Code c++ : 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
    #include <type_traits>
    #include <iostream>
     
    using namespace std;
     
    typedef enum{
    	Add,
    	Mult,
    } Expression;
     
    typedef struct {} EA;
    typedef struct {} EB;
     
    template<class L,class R, Expression E> class Expr;
     
    template<class L,class R>
    class Expr<L,R,Mult>
    {
    public:
    	Expr(const L& left, const R& right, const EA& dummy){}
    	inline void exec(){ cout << "class\n"; }
    };
     
    template<class L,class R>
    class Expr<L,R,Mult>
    {
    public:
    	Expr(const L& left, const R& right, const EB& dummy){}
    	inline void exec(){ cout << "arithmetic\n"; }
    };
     
    template<class L,class R>
    inline Expr<L,R,Mult> operator*(const L& left, const R& right){
    	return Expr<L,R,Mult>(left, right, typename conditional<is_class<L>::value && is_class<R>::value, EA, EB>::type());
    }
     
    class A{
    public:
    	A(){}
    };
     
    int main(){
    	A a;
    	int x = 3;
    	float y = 0.5;
    	(a*a).exec();
    	(a * x).exec();
    	(y * a).exec();
    	return 0;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    test.cpp:36:7: error: redefinition of ‘class Expr<L, R, (Expression)1u>’
    test.cpp:28:7: error: previous definition of ‘class Expr<L, R, (Expression)1u>’
     
    test.cpp:45:115: error: no matching function for call to ‘Expr<A, int, (Expression)1u>::Expr(const A&, const int&, std::conditional<false, EA, EB>::type)’
    test.cpp:45:115: note: candidates are:
    test.cpp:31:2: note: Expr<L, R, (Expression)1u>::Expr(const L&, const R&, const EA&) [with L = A; R = int]
    test.cpp:31:2: note:   no known conversion for argument 3 from ‘std::conditional<false, EA, EB>::type {aka EB}’ to ‘const EA&’

  7. #7
    En attente de confirmation mail

    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 : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Le problème c'est que tu fais surtout deux fois la même spécialisation partielle.

    Il n'y a que exec qui dépend du type dummy ? Dans ce cas, c'est lui qui doit utiliser la technique du tag dispatching : une seule classe, mais deux fonction exec_impl en private dans celle-ci.

  8. #8
    Membre expérimenté Avatar de davcha
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 258
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 258
    Points : 1 539
    Points
    1 539
    Par défaut
    En effet, je suis bête.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Templates] Quel système utilisez-vous ? Pourquoi ?
    Par narmataru dans le forum Bibliothèques et frameworks
    Réponses: 270
    Dernier message: 26/03/2011, 00h15
  2. Template XHTML
    Par Sylvain James dans le forum XSL/XSLT/XPATH
    Réponses: 14
    Dernier message: 16/06/2003, 21h45
  3. appliquer plusieurs templates
    Par Manu_Just dans le forum XSL/XSLT/XPATH
    Réponses: 7
    Dernier message: 04/04/2003, 16h26
  4. template match="node() mais pas text()"
    Par Manu_Just dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 26/03/2003, 10h52
  5. [XSLT] template
    Par demo dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 09/09/2002, 11h31

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