OVH Cloud OVH Cloud

Template, argument par defaut et declaration en avant

35 réponses
Avatar
Marc Boyer
Bonjour,

bon, je reprends un (gros) code C++, alors je vais avoir je crois pas
mal de questions.

Pour le moment, j'ai un problème de template + argument template par defaut
+ declaration en avant.

Soit une classe avec un argument template par defaut, genre
template <class T,
template <class X> cont= std::list>
class Collection {
T t;
cont<int> c;
};

J'ai besoin dans une autre classe de faire une déclaration en avant,
mais comme je ne fixe pas dans ce cas de valeur au 2ème argument
template, il faut que je fasse une déclaration en avant complète:
template <class T,
template <class X> cont= std::list>
class Collection;

Et quand je définis la classe, il rale d'une redéclaration
des arguments par défaut...

J'ai pensé à un fichier du genre
CollectionFwd.h
dans la même veine que
iosfwd
mais est-ce que je sors pas le marteau pour écraser une mouche ?

Est-ce qu'il y a des pratiques "habituelles" ?

Vous faites comment vous ?

Marc Boyer
--
La contractualisation de la recherche, c'est me donner de l'argent pour
faire ce que je ne sais pas faire, que je fais donc mal, pendant que ce
que je sais faire, je le fais sans moyens...

5 réponses

1 2 3 4
Avatar
Jean-Marc Bourguet
Gabriel Dos Reis writes:

Jean-Marc Bourguet writes:

[...]

| > Du coup, on a la chaine d'heritage suivante
| >
| > Var_impl -> Decl_impl<> -> Expr_impl -> Var -> Decl -> Expr

Ai-je mal compris ta question ?


Il me semble mais c'est peut-etre moi qui n'ai pas ete clair.
Reessayons avec quelque chose de legerement different. Je suppose
qu'il y a autre chose que des Var qui sont des Decl. Par exemple des
Func. On a donc

Func_impl -> Decl_impl<F> -> Expr_impl<F> -> Func
}-> Decl -> Expr
Var_impl -> Decl_impl<V> -> Expr_impl<V> -> Var /

Maintenant j'ai a ecrire une fonction qui peut aussi bien prendre un
Func_impl qu'un Var_impl. Avec la struture en heritage, je lui aurais
fait prendre un Decl_impl. Ici, ce n'est plus possible, il faut au
choix lui passer un Decl et donc n'utiliser que l'interface publique
ou rendre ma fonction template ce qui revient a dupliquer du code
inutilement. Est-ce qu'il y a quelque chose que j'ai manque?

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Gabriel Dos Reis
Jean-Marc Bourguet writes:

| Gabriel Dos Reis writes:
|
| > Jean-Marc Bourguet writes:
| >
| > [...]
| >
| > | > Du coup, on a la chaine d'heritage suivante
| > | >
| > | > Var_impl -> Decl_impl<> -> Expr_impl -> Var -> Decl -> Expr
|
| > Ai-je mal compris ta question ?
|
| Il me semble mais c'est peut-etre moi qui n'ai pas ete clair.
| Reessayons avec quelque chose de legerement different. Je suppose
| qu'il y a autre chose que des Var qui sont des Decl. Par exemple des
| Func. On a donc
|
| Func_impl -> Decl_impl<F> -> Expr_impl<F> -> Func
| }-> Decl -> Expr
| Var_impl -> Decl_impl<V> -> Expr_impl<V> -> Var /
|
| Maintenant j'ai a ecrire une fonction qui peut aussi bien prendre un
| Func_impl qu'un Var_impl.

Oui, uniquement si tu fais une operation de mutation, ou si tu crées
un noeud (mais alors dans ce cas, tu as de toute façon besoin de savoir
que c'est un Var_impl ou un Func_decl_impl, indépendamment d'heritage
multiple ou non).

| Avec la struture en heritage, je lui aurais
| fait prendre un Decl_impl.

Oui, mais le point crucial est : qu'est-ce que tu ferais avec un
Decl_impl sans avoir d'autres informations qui diffèrent d'un noeud à
l'autre ? (Je peux penser à certaines opérations, mais ce sont des
invariants qui existent au moment de la création).
Var et Fun_decl maintiennent des informations de type qui ne
sont pas les mêmes et ne sont que très abstraitement décrites par
Decl. Par exemple, le type Var -- virtuellement n'importe quel type --
est différent ce lui de Fun_decl -- qui a la structure
{return-type, parameter-type-list, ex-spec}.

| Ici, ce n'est plus possible, il faut au
| choix lui passer un Decl et donc n'utiliser que l'interface publique
| ou rendre ma fonction template ce qui revient a dupliquer du code
| inutilement. Est-ce qu'il y a quelque chose que j'ai manque?

Je crois que le fond est : quelles opérations veux-tu faire à un
Decl_impl ?

-- Gaby
Avatar
Jean-Marc Bourguet
Gabriel Dos Reis writes:

Jean-Marc Bourguet writes:

| Gabriel Dos Reis writes:
|
| > Jean-Marc Bourguet writes:
| >
| > [...]
| >
| > | > Du coup, on a la chaine d'heritage suivante
| > | >
| > | > Var_impl -> Decl_impl<> -> Expr_impl -> Var -> Decl -> Expr
|
| > Ai-je mal compris ta question ?
|
| Il me semble mais c'est peut-etre moi qui n'ai pas ete clair.
| Reessayons avec quelque chose de legerement different. Je suppose
| qu'il y a autre chose que des Var qui sont des Decl. Par exemple
| des Func. On a donc
|
| Func_impl -> Decl_impl<F> -> Expr_impl<F> -> Func
| }-> Decl -> Expr
| Var_impl -> Decl_impl<V> -> Expr_impl<V> -> Var /
|
| Maintenant j'ai a ecrire une fonction qui peut aussi bien prendre
| un Func_impl qu'un Var_impl.

Oui, uniquement si tu fais une operation de mutation, ou si tu crées
un noeud (mais alors dans ce cas, tu as de toute façon besoin de
savoir que c'est un Var_impl ou un Func_decl_impl, indépendamment
d'heritage multiple ou non).

| Avec la struture en heritage, je lui aurais fait prendre un
| Decl_impl.

Oui, mais le point crucial est : qu'est-ce que tu ferais avec un
Decl_impl sans avoir d'autres informations qui diffèrent d'un noeud
à l'autre ?


A Decl_impl? Rien de particulier. Je cherche a savoir a quel point
la technique est generale comme remplacante de celle utilisant
l'heritage multiple en prenant vos noms comme exemple. J'aurais
peut-etre du le preciser.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Gabriel Dos Reis
Jean-Marc Bourguet writes:

| Gabriel Dos Reis writes:
|
| > Jean-Marc Bourguet writes:
| >
| > | Gabriel Dos Reis writes:
| > |
| > | > Jean-Marc Bourguet writes:
| > | >
| > | > [...]
| > | >
| > | > | > Du coup, on a la chaine d'heritage suivante
| > | > | >
| > | > | > Var_impl -> Decl_impl<> -> Expr_impl -> Var -> Decl -> Expr
| > |
| > | > Ai-je mal compris ta question ?
| > |
| > | Il me semble mais c'est peut-etre moi qui n'ai pas ete clair.
| > | Reessayons avec quelque chose de legerement different. Je suppose
| > | qu'il y a autre chose que des Var qui sont des Decl. Par exemple
| > | des Func. On a donc
| > |
| > | Func_impl -> Decl_impl<F> -> Expr_impl<F> -> Func
| > | }-> Decl -> Expr
| > | Var_impl -> Decl_impl<V> -> Expr_impl<V> -> Var /
| > |
| > | Maintenant j'ai a ecrire une fonction qui peut aussi bien prendre
| > | un Func_impl qu'un Var_impl.
| >
| > Oui, uniquement si tu fais une operation de mutation, ou si tu crées
| > un noeud (mais alors dans ce cas, tu as de toute façon besoin de
| > savoir que c'est un Var_impl ou un Func_decl_impl, indépendamment
| > d'heritage multiple ou non).
| >
| > | Avec la struture en heritage, je lui aurais fait prendre un
| > | Decl_impl.
| >
| > Oui, mais le point crucial est : qu'est-ce que tu ferais avec un
| > Decl_impl sans avoir d'autres informations qui diffèrent d'un noeud
| > à l'autre ?
|
| A Decl_impl? Rien de particulier. Je cherche a savoir a quel point
| la technique est generale comme remplacante de celle utilisant
| l'heritage multiple en prenant vos noms comme exemple. J'aurais
| peut-etre du le preciser.

Nous ne prétendons pas que ce soit une solution universelle :-)
Loin de là. Nous avons adopter cette solution après examen des
opérations que supportent les classes d'interface et les classes
d'implémentation.

Ce qui n'apparaît pas sur les transparents, c'est que les interfaces
(qui suivent la tradition OO) donnent accès à pratiquement toutes les
informations dont on aurait besoin de construire dans la partie
implémentation.
Les classes d'implémentation fournissent essentiellement des
« setters » -- quoique nous essayons de minimiser leur nombre en
mettant l'accent sur les informations necessaires pour créer un noeud
correctement. Par exemple, pour créer un noeud de class dérivée de
Decl, il est nécessaire d'avoir le nom et le type. Il n'est pas
possible de créer le noeud puis de mettre le nom ou le type après.
Ce sont des invariants d'un Decl. On les utilise, par exemple, pour
gérer les overload-set correctement ou lier les déclarations
maîtresses avec les déclarations secondaires.

-- Gaby
Avatar
Jean-Marc Bourguet
Gabriel Dos Reis writes:

Jean-Marc Bourguet writes:

| Je cherche a savoir a quel point la technique est
| generale comme remplacante de celle utilisant l'heritage
| multiple en prenant vos noms comme exemple. J'aurais
| peut-etre du le preciser.

Nous ne prétendons pas que ce soit une solution universelle :-)


Ce n'était pas présenté comme ça. Comme j'ai eu à utiliser
l'autre approche, j'en connais trop bien les inconvéniants.
Le slide présentait une technique alternative, j'en
cherchais les limites pour pouvoir avoir une approche
technologique et choisir la technique appropriée au
problème.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

1 2 3 4