OVH Cloud OVH Cloud

Curiously reccuring template patterns, et types

1 réponse
Avatar
Laurent Rineau
(Ceci est mon premier message dans fr.comp.lang.c, et m

1 réponse

Avatar
Gabriel Dos Reis
Laurent Rineau writes:

| (Ceci est mon premier message dans fr.comp.lang.c, et même sur Usenet en
| général.)
|
| On peut faire ce genre de choses en C++ :
|
| template <typename Model>
| struct Concept {
|
| Model& self()
| {
| return static_cast<Model&>(*this);
| }
|
| void f()
| {
| self.f_impl();
| }
| };
|
| struct Model: public Concept<Model>
| {
| void f_impl() {};
| };
|
| Ainsi, Model::f() est une fonction de la superclass Concept dont le
| comportement dépend de la classe dérivée Model. C'est décrit dans [1] (si
| d'ailleurs quelqu'un peut me dire comment lire ce genre de chose, il faut
| être abonné ?).

« The C++ Report » n'existe plus. Il faut se tourner vers CUJ et
affiliés (regarde sur le site de ACCU).

|
| Bizarrement, on ne peut pas faire en sorte que Concept utilise un type
| défini dans Model :
|
| template <typename Model>
| struct Concept {
|
| Model& self()
| {
| return static_cast<Model&>(*this);
| }
|
| typedef typename Model::f_return_type f_type; // ligne 9
|
| f_type f()
| { // ligne 12
| return self.f_impl();
| }
| };
|
| struct Model: public Concept<Model> // ligne 17
| { // ligne 18
| typedef int f_return_type;
|
| f_return_type f_impl() { return 0; };
| };
|
| J'obtiens les erreurs suivantes :
|
| essai2.C: In instantiation of `Concept<Model>':
| essai2.C:18: instantiated from here
| essai2.C:9: invalid use of undefined type `struct Model'
| essai2.C:17: forward declaration of `struct Model'
| essai2.C:12: invalid use of undefined type `struct Model'
| essai2.C:17: forward declaration of `struct Model'
|
| Quelqu'un sait-il pourquoi exactement ?

Une classe qui sert de classe de base doit être complète. Or lors que que tu
écris

struct Model : Concept<Model>

le compilateur doit instantier Concept<Model>, pour pouvoir disposer
d'un type complet. À cet instant là, on ne sait pas encore à quoi
ressemble la portée définie par Model. Pendant l'instantiation de
Concept<Model>, le compilateur voit que tu utilises
Model::f_return_type. Donc, il va essayer de fouiller dans la portée
définie par Model s'il y existe un f_return_type. Mais, il ne peut pas
parce que cette portée n'a même pas commercé à exister. Donc erreur.

| La définition de Model provoque
| l'instanciation de Concept<Model>. Alors que, bizarrement, le fait que
| Model::f_impl() soit défini après la ligne 18 ne gène pas le comp ilateur,
| le fait que Model::f_return_type le soit semble provoquer
| l'erreur. Pourquoi cette différence ?

Voir ci-haut en ce qui concerne Model::f_return_type. En complément,
tu as les faits suivants :

(1) l'instantiation de Concept<Model> est implicite ;
(2) pendant une instantiation implicite d'une classe, on inistantie
*que* les déclarations contenues dans la classe (et non les
définitions). Les déclarations d'amitié qui sont auss i des
définitions font une bande à part ;
(3) pour déclarer une fonction (et non définir), on n'a pas bes oin
que le type de retour soit complet -- juste qu'il soit déclarà ©.

-- Gaby