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 :

Fonction membre template et polymorphisme


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    159
    Détails du profil
    Informations personnelles :
    Localisation : France, Moselle (Lorraine)

    Informations forums :
    Inscription : Mai 2007
    Messages : 159
    Par défaut Fonction membre template et polymorphisme
    Bonjour,

    J'aurais besoin de pouvoir utiliser le polymorphisme sur une fonction membre template.
    Je sais que c'est interdit, mais y aurait-il une solution de contournement?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class A { 
        virtual template <unsigned _V> auto F() -> int; // Interdit
    }
     
    class B : public A
    {
        template <unsigned _V> auto F() -> int override;
    ];
     
    int main(int, char*[] )
    {
        A *a = new B;
        auto c = a->f<6>();
    }
    Par avance merci de vos réponses

    @+++
    Marc

  2. #2
    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,

    Oui, il suffit de créer une fonction virtuelle qui n'est pas template

    D'ailleurs, c'est bien simple : pourquoi voudrais tu créer une fonction template (dont les types requis sont déterminés à la compilation)

    Ceci étant dit, il y a moyen de combiner l'approche générique des template avec l'approche orientée objet des fonctions virtuelles, par exemple, en ayant une classe template qui hérite d'une classe qui ne l'est pas, sous une forme qui serait dés lors 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
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    /* une classe de base, non template, ayant sémantique d'entité */
    class Base{
    publlic:
        /* les classes qui intereviennent dans une hiérarchie de classe
         * sont, idéalement, non copiable et non assignables 
         */
        Base(Base const &) = delete;
        Base & operator=(Base const &) = delete;
        virtual ~Base() = default;
        /* une fonciton virtuelle, dont le comportement sera redéfini dans les classes dérivées */
        virtual void foo() /*const */ /* = 0*/;
    };
    /* une classe template, dont les données membres dépendront du paramètre template,
     * qui dérive de la classe de base
     */
    template <typename A/*, typename ... ARGS */>
    class Derived : public Base{
    public:
        void foo() /* const */ override[
            /* ce qui doit être fait */
        }
    private:
        A data_; // la donnée membre nécessaire au service qui doit être rendu par foo
    }
    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

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    159
    Détails du profil
    Informations personnelles :
    Localisation : France, Moselle (Lorraine)

    Informations forums :
    Inscription : Mai 2007
    Messages : 159
    Par défaut
    Bonjour,

    Oui, il suffit de créer une fonction virtuelle qui n'est pas template
    Ca m'aurait étonné

    D'ailleurs, c'est bien simple : pourquoi voudrais tu créer une fonction template (dont les types requis sont déterminés à la compilation)
    La réponse est aussi simple : parce qu'il y a les deux aspects. J'utilise ici les modèles pour faire du paramétrique :
    - J'ai un ensemble de classes ayant un comportement paramétré (avec un entier en l'occurrence), dont le paramètre est connu à la compilation, ET NE PEUT PAS être passé en argument, car alors il n'est plus connu à la compilation. La fonction introduit et/ou participe à des enchainements de fonctions utilisant ce paramètre. Le nombre de valeurs valides du paramètre peut varier au cours du temps (de la vie du programme), mais est toujours connu à la compilation. Cela dit, il m'apparaît comme très compliqué, et impossible à gérer, de créer une fonction par valeur. De plus, j'ai un mécanisme qui provoque l'utilisation de telle ou telle fonction en fonction de la valeur du paramètre.
    - Pendant le cours du programme, à un moment, l'utilisateur doit pouvoir choisir une de ces classes (au travers d'un objet) pour y appliquer une opération 'standard' (la fonction f), donc typiquement du polymorphisme.
    - L'utilisateur ne choisira jamais le paramètre (c'est un paramètre calculé au préalable et qui lui est imposé).
    - La dernière raison est pour moi : je ne savais pas qu'il n'est pas possible de rendre une fonction paramétrique virtuelle... Du coup, j'ai créé tout le réseau de fonctions sans me préoccuper de cet aspect. Ce n'est que quand j'ai implémenté ma classe de base que je suis tombé sur cet os... Du coup, faute de conception... Encore que, je ne vois pas très bien comment j'aurais pu concevoir tout ça autrement.

    Je vais analyser ta proposition, et reviendrai dire comment cela se passe (sans doute lundi ou mardi).
    En tous cas, merci pour ta réponse!

    Cordialement,
    Marc

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    159
    Détails du profil
    Informations personnelles :
    Localisation : France, Moselle (Lorraine)

    Informations forums :
    Inscription : Mai 2007
    Messages : 159
    Par défaut
    Tes idées m'inspirent vraiment! Merci!

    Voici ce qui en est sorti :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    class Base {
        template <unsigned _V> struct F { /*...*/ virtual auto  f(Base &, /* args */) -> ret = 0; }; // classe de base virtuelle pure
    public:
        template <unsigned _V> auto f(/* args */) -> ret { return F().f(*this, /* args */); }
    };
     
    class Derivee {
        template <unsigned _V> struct Fd { /* ... */ auto f(Derivee &cible, /* args */) -> ret { return cible.f<_V>(); }  // Sais plus si ça marche... Ça compile en tous cas.
        template <unsigned _V> struct Fd { /* ... */ auto f(Base &cible,/* args */) -> ret { return dynamic_cast<Derivee &>(cible).f<_V>(); } // Ça semble plus sur.
        template <unsigned _V> auto f(/* args */) -> ret { /* mon action */ }
    };
    Bien entendu, il faut que toutes les classes dérivées implémentent une classe Fd.
    Très dangereux, car sinon insulte à l'exécution du type "Pure virtual fonction called..." : rien n'oblige à la création de la classe dérivée covariante, et donc l'erreur n'apparaîtra qu'en cours d'exécution.
    Un moyen d'éviter ce problème (à part ne pas le faire, ce que je peux comprendre comme conseil)?

    Cordialement,
    Marc

  5. #5
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 502
    Par défaut
    ET NE PEUT PAS être passé en argument, car alors il n'est plus connu à la compilation.
    Bin si, "constexpr" est ton ami.
    https://en.cppreference.com/w/cpp/language/constexpr
    donc typiquement du polymorphisme.
    Bin non, la composition est bien plus flexible.
    Pourquoi le Design Pattern Stratégie ne s'adapte pas à votre besoin ?

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    159
    Détails du profil
    Informations personnelles :
    Localisation : France, Moselle (Lorraine)

    Informations forums :
    Inscription : Mai 2007
    Messages : 159
    Par défaut
    Bonjour,

    Tout d'abord oups, faute de carre...
    Dans ma solution je tente d'instancier une classe abstraite. Heureusement, le ridicule ne tue pas...

    @bacelar :
    - constexpr, comme les paramètres template, est incompatible avec virtual (une fonction virtuelle ne peut être constexpr, et constexpr ne peut pas être utilisé sur un argument)
    - Le motif stratégie se rapproche effectivement de ce que je veux faire. Je vais l'étudier de près, sachant que mon problème sera toujours de transmettre mon paramètre pendant la compilation.
    Merci à toi, Bacelar!

    Cordialement,
    Marc
    .

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 09/04/2009, 11h30
  2. [C++] fonction membre template
    Par Luc Hermitte dans le forum BOUML
    Réponses: 3
    Dernier message: 03/02/2009, 23h01
  3. Problème de spécialisation de fonction membres template
    Par ludovic.barrillie dans le forum Langage
    Réponses: 3
    Dernier message: 17/04/2007, 08h44
  4. Pointeur de fonction membre template
    Par bolhrak dans le forum Langage
    Réponses: 6
    Dernier message: 12/12/2006, 14h47
  5. Réponses: 5
    Dernier message: 29/12/2005, 21h27

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