Page 1 of 1

templates et définitions

PostPosted: Sun 4 Nov 2012 17:02
by Teaniel
Bonjour,

Au chapitre des nouveautés de C++11, en rapport avec les fonctions et classes génériques, il n'est plus nécessaire de présenter toute la définition de la classe à son utilisateur.
On peut maintenant se comporter avec ces fonctions comme avec les fonctions normales (une déclaration externe dans le .h et la définition dans le .cpp).
Dans ce cadre là, je pense qu'il n'est plus nécessaire de forcer la propriété inline des fonctions des classes template (pour l'instant elle est grisée dans l'interface).

Cordialement,
Marc

Re: templates et définitions

PostPosted: Mon 5 Nov 2012 15:50
by Bruno Pagès
Bonjour,

là je ne suis pas d'accord, une opération utilisant un paramètre formel doit impérativement être définie dans le fichier d'en-tête

Re: templates et définitions

PostPosted: Tue 6 Nov 2012 19:53
by Teaniel
Bonjour,

Ben... Je vous propose d'essayer. C'est ce que j'ai fait avant de poster cette demande, avec QT et g++.
J'ai créé une classe générique, comme d'habitude, en la mettant (déclaration et définitions) dans le header.
Après avoir lu un truc (désolé je ne me rappelle plus où tout ce que je me souviens c'est que c'était en anglais) sur le sujet, ça m'a pris d'essayer, en déplaçant toutes les définitions des fonctions de ma classe dans le .cpp, et tout a fonctionné. J'ai pu vérifier dans le debugger que je passais bien dans les fonctions que j'avais ainsi définies.
Je vais, pour bétonner, refaire un essai en créant un projet spécialement pour ça et je vous tiens au courant.

Cordialement,
Marc

Re: templates et définitions

PostPosted: Wed 7 Nov 2012 12:26
by Teaniel
Bonjour,

Veuillez accepter mes excuses, en effet je n'arrive pas à reproduire ce que j'ai fait.
J'avais pris l'info ici, et l'ai mal interprétée: http://en.wikipedia.org/wiki/C%2B%2B11#Extern_template
A l'endroit où elles sont instanciées, les classes doivent toujours être complètement définies.
Ceci dit, ce que j'ai indiqué avoir fait dans le post précédent, je l'ai réellement fait, et je n'ai pas encore compris pourquoi ça marche. A aucun moment je n'instancie explicitement la classe que j'ai développée, et j'ai effectivement déplacé la définition des fonctions dans le cpp.
De fait, si on externalise les fonctions, il semble qu'il soit obligatoire d'y ajouter une instanciation explicite sans quoi on se prend une erreur type 'référence à fonction maclasse<int>::maclasse() non définie'.
Finalement, en utilisant le mot-clé extern qui permet d'empêcher l'instanciation immédiate, et l'instanciation explicite dans le cpp, on peut effectivement écrire les classes template comme je le souhaite (simplement, dans ce cas là, on limite l'utilisation de la classe aux génériques instanciés, sans permettre à l'utilisateur d'en créer de nouveaux).
Et c'est la raison pour laquelle, si vous voulez bien, je maintiens ma demande.

Cordialement,
Marc

Re: templates et définitions

PostPosted: Wed 7 Nov 2012 13:36
by Bruno Pagès
Bonjour,

je ne comprends pas ce que vous voulez dire, pouvez vous donner un exemple de code à générer ?

Re: templates et définitions

PostPosted: Wed 7 Nov 2012 14:38
by Teaniel
Bien sur :)

header a.h:
Code: Select all
template <class T> class A {
    T p;
    public:
    A();
};
// Déclaration n'impliquant pas l'instanciation des classes.
extern template class A<int>;
extern template class A<double>;

source a.cpp:
Code: Select all
template <class T> A<T>::A() : p() {}

// Ici on instancie les template :
template class A<int>;
template class A<double>;

utilisation :
Code: Select all
#include "A.h"

...
A<int> Aint;
...
A<double> Adouble;
...


Voila exactement ce que je souhaitais pouvoir faire.
Je comprends bien que cela implique et n'est réalisable que si je connais exhaustivement les types que cette classe utilisera. En effet, le fait de cacher la définition des fonctions à l'utilisateur signifie que celui-ci ne pourra pas en générer d'autres. Dans mon projet c'est parfaitement assumé.
Notez que cela fonctionnait déjà avant c++11, sauf que le mot clé extern ne pouvant être utilisé, l'instanciation se faisait à chaque point d'utilisation. extern apporte un gain de performances au compilateur.

Voila pourquoi je souhaiterais pouvoir décocher la case 'inline' dans la définition d'une fonction membre de classe paramétrée. :)

Cordialement,
Marc

Re: templates et définitions

PostPosted: Wed 7 Nov 2012 16:01
by Bruno Pagès
mais le constructeur pourrait tout aussi bien être défini dans le fichier d'en-tête, ce qui n'occasionne pas instanciation supplémentaire dans votre cas

la seule différence que je vois est que dans votre cas il est impossible de faire une instanciation avec un paramètre actuel autre que int et double car cela produirai une erreur à l'édition de liens, c'est ca le but ultime de la chose ?

Re: templates et définitions

PostPosted: Wed 7 Nov 2012 18:17
by Teaniel
Bonjour,

Ça pourrait l'être, en effet.
Mon objectif est surtout de ne pas être obligé de présenter les définitions des fonctions au client (en particulier dans les cas où on se retrouve avec des dépendances cycliques).
Exemple où cette construction m'est indispensable (exemple minimaliste):
Code: Select all
template <class T> class base {
public:
   static base *Create(int i);// i me sert de sélecteur de construction, il peut être n'importe quoi
};

template <class T> class derivee1 : public base<T> {};
template <class T> class derivee2 : public base<T> {};
template <class T> class derivee3 : public base<T> {};
template <class T> class derivee4 : public base<T> {};

base *base::Create(int i) {
    switch(i) {
        case 1: return new derivee1;
        case 2: return new derivee2;
        case 3: return new derivee3;
...
   }
}

main() {
...
base<double> *obj = base<double>::Create(3);
...
}

Dans ce cas, Create ne peut être inclus dans le header si les classes dérivées n'y sont pas aussi (cas de l'organisation 1 classe = 1 artifact).
Egalement Create est obligé de connaître toutes les classes qu'il doit créer. On se retrouve donc ici avec une dépendance cyclique. Par conséquent, cette fonction ne peut être définie ailleurs que dans un .cpp.
C'est très précisément dans cette situation que je me trouve dans mon projet.

Voila.
Cordialement,
Marc

Re: templates et définitions

PostPosted: Thu 8 Nov 2012 07:25
by Bruno Pagès
Bonjour,

ah oui, je n'avais pas pensé aux cycles

je vais rendre modifiable l'option inline dans le cas d'une opération dans une classe paramétrée. Bien évidemment la première fois que l'on ajoutera des paramètres formels à une classe cela forcera inline pour ses opérations, et par défaut une opération ajoutée à une classe paramétrée sera également inline.

cela implique aussi la modification du générateur, et des reverse/roundtrip (en plus de la correction du cas && dans les paramètres pour ces derniers).

Re: templates et définitions

PostPosted: Sun 2 Dec 2012 22:03
by Bruno Pagès
La version 6.4 est disponible, l'option inline peut maintenant être décochée pour les opérations des classes paramétrées.