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 :

Hésitation sur la conception de patrons de classes


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de Seabirds
    Homme Profil pro
    Post-doctoral fellow
    Inscrit en
    Avril 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Post-doctoral fellow
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2015
    Messages : 294
    Par défaut Hésitation sur la conception de patrons de classes
    Bonjour à toutes et à tous !

    J'utilise depuis quelques temps déjà les templates pour mettre de la variabilité sur les types, mais je n'ai jamais été confronté au problème suivant :

    Soit un concept A (un ensemble de distribution de probas dans mon cas), proposant un service sample() dont le résultat peut être :
    - constant
    - variable dans un espace X
    - variable un espace X et un autre espace Y.

    Grand naïf, j'ai pensé faire ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class A;
    template<typename X> A;
    template<typename X, typename Y> A;
    Le service commun varie dans ses arguments : sample(), sample(X), ou sample(X, Y) et l'implémentation varie selon les cas. Du coup je ne sais pas si je dois/peux donner le même nom à ces patrons de classes:
    • D'un côté si leur implémentation et leur service varie, c'est qu'ils ont pas grand chose à voir.
    • D'un autre côté ces sont tous des A, du coup j'ai eu envie de tous les nommer pareil avec l'idée que le nombre d'arguments template suffiraient à lever l'ambiguité. Le compilateur me signale aimablement que je n'y connais rien "class A redeclared with ... argument template", ce dont je lui sais gré.


    Du coup j'hésite entre
    • renommer les patrons de classe Foo, XVariableFoo, XYVariableFoo mais même si ça a l'air d'être la solution la plus facile quelque chose me dit que ça cloche
    • en apprendre plus sur toute autre approche que vous identifiriez comme étant une meilleure solution problème (peut être faut il donner à tout le monde le même nombre d'arguments template et utiliser des trucs du genre dispatch/enable_if/traits... )


    Qu'en pensez-vous ?

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 152
    Billets dans le blog
    4
    Par défaut
    Je pense que pour lever ton ambiguité tu dois faire une classe avec variadic template que tu spécialises pour tes 3 cas : 0, 1 et 2 templates.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Membre éclairé Avatar de Seabirds
    Homme Profil pro
    Post-doctoral fellow
    Inscrit en
    Avril 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Post-doctoral fellow
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2015
    Messages : 294
    Par défaut
    Merci pour la piste je vais aller chercher ça !

  4. #4
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    En fait, il y a plusieurs choses qui pourraient être intéressantes à faire...

    La première serait de définir un "tag" représentant chacune des variations possibles, sous une forme qui pourrait être proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    struct tagNone{
        using tag_type = tagNone;
    };
    struct tagOne{
        using tag_type = tagOne;
    };
    struct tagTwo{
        using tag_type = tagTwo;
    };
    Ce genre de tag n'apporte rien en soi à part le fait de pouvoir "tagger" les différents éléments selon leur appartenance à à l'une ou l'autre des catégories et de te faciliter énormément la vie lorsqu'il s'agit de s'assurer du type que tu manipule, par exemple, sous la forme d'un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <typename T1, typename T2>
    class MaClass{
        static_assert(std::is_same(typename T1::tag_type, typename T2::tag_type>::value,
                                                  "first and second template parameter should be same type");
    },
    Ce tag te permettra alors de définir les politiques particulières propres à chacun des ensemble, par exemple sous la forme de
    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 TAG> struct Policy;
    template <>
    struct Policy<tagNone>{
        /* aucun paramètre requis pour tagNone */
        TypeDeRetour operator()() const{
            /* à toi de voir ce que tu fais ;) */
        }
    };
    template <>
    struct Policy<tagNone>{
        /* un paramètre requis pour tagOne */
        TypeDeRetour operator()(TypeParam) const{
            /* à toi de voir ce que tu fais ;) */
        }
    };
    template <>
    struct Policy<tagTwo>{
        /* deux paramètre requis pour tagTwo */
        TypeDeRetour operator()(T1,  T2) const{
            /* à toi de voir ce que tu fais ;) */
        }
    };
    Et, à partir de là, tu gagnes toute la liberté que tu veux, par exemple, en créant ton ensemble A sous une forme qui pourrait être proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    template <typename TAG>
    struct A{
        /* si pas tagNone, tagOne ou tagTwo, on risque une erreur de comilation ici...
         * un static_assert serait sand doute plus clair ... d'autant que tu as peut être
         * d'autres tag que ces trois là qui risquent de définir tag_type 
         */
        using tag_type = typename TAG::tag_type;
        using policy_type = Policy<tag_type>;
        template <typename ... Args>
        void foo(Args ... args){
            /* si ca ne correspond pas, l'erreur aura lieu ici à la compilation */
            policy_type()(args ...);
        }
    };
    Mais tu pourrais aussi envisager quelque chose à base de std::enable_if ou autres solutions contorsionnée Le tout étant de toujours te donner l'occasion de récupérer le type de tag sous une forme ou une autre
    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

  5. #5
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 513
    Par défaut
    Bonjour Seabirds.

    Voici un exemple de bout de code qui respecte la description de ton message et qui utilise l'astuce que vient de donner Bousk :
    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    #include <iostream>
    #include <random>
     
    template<class ...T>
    class A;
     
    template<>
    class A<>
    {
    public:
    	constexpr static int sample() noexcept
    	{
    		return 0;
    	}
    };
     
    template<class TX>
    class A<TX>
    {
    public:
    	TX sample(TX x)
    	{
    		return x*m_d(m_rd);
    	}
    private:
    	std::random_device                 m_rd;
    	std::uniform_real_distribution<TX> m_d;
    };
     
    template<class TX, class TY>
    class A<TX, TY>
    {
    public:
    	std::pair<TX, TY> sample(TX x, TY y)
    	{
    		return std::make_pair(x*m_d1(m_rd), x*m_d2(m_rd));
    	}
    private:
    	std::random_device                 m_rd;
    	std::uniform_real_distribution<TX> m_d1;
    	std::uniform_real_distribution<TY> m_d2;
    };
     
    int main()
    {
    	A<>              a1;
    	A<float>         a2;
    	A<float, double> a3;
    	const int                      s1 = a1.sample();
    	const float                    s2 = a2.sample(5.0f);
    	const std::pair<float, double> s3 = a3.sample(10.0f, 21.0);
    	std::cout << "s1 : " << s1 << '\n';
    	std::cout << "s2 : " << s2 << '\n';
    	std::cout << "s3 : (" << s3.first << " ; " << s3.second << ")\n";
    	return 0;
    }
    Cela dit, au niveau de la conception, le code que je viens d'écrire est assez étrange.
    Peux-tu nous en dire plus sur les variables membres de ton modèle de classe A, sur tes espaces X et Y et sur tes fonctions sample ?
    Peut-être que, en en sachant plus, on te conseillera de structurer le code différemment.

  6. #6
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    La grosse question est souvent toujours la même quand on parle de template: "Quand l'utilisateur du code devra-t-il choisir?".

    Es-tu certain que le programme utilisateur doive savoir à la compilation qu'elle type de distribution il veut utiliser.
    Es-tu certain de ne pas vouloir qu'il puisse stocker dans un même vecteur des distributions à 0, 1 ou 2 paramètres?

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 02/10/2016, 22h51
  2. Question sur la conception d'une classe type Logger
    Par NLS le pingouin dans le forum C++
    Réponses: 14
    Dernier message: 01/11/2010, 13h36
  3. Hésitation sur le choix de PostGreSQL
    Par brice01 dans le forum Décisions SGBD
    Réponses: 3
    Dernier message: 13/12/2004, 17h48
  4. [Débutant][Conception] Erreur avec une classe interne
    Par Devil Redneck dans le forum Général Java
    Réponses: 5
    Dernier message: 11/06/2004, 15h45
  5. Recherche Livre / Conseils sur la conception de Base
    Par Yeuma dans le forum Décisions SGBD
    Réponses: 7
    Dernier message: 02/01/2004, 14h25

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