Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

encore du templates : fonction non dépendante de l'argument template

2 réponses
Avatar
meow
Hello,

J'ai une classe A templat=E9e qui comprend une fonction non templat=E9e
int degree()
et le compilo me crie
"there are no arguments to 'degree' that depend on a template
parameter, so a declaration of 'degree' must be available"
a chaque utilisation de degree dans d'autres fonctions de ma classe A
j'ai r=E9solu le probleme en prefixant lesdits appels par "this->"
N=E9anmoins j'aimerai comprendre en quoi il y a difficult=E9 pour le
compilo de remarquer que, templat=E9 ou non, il existe bien un symbole
degree() dans A<T> ?

2 réponses

Avatar
kanze
meow wrote:

J'ai une classe A templatée qui comprend une fonction non
templatée int degree()


Mais membre de la classe templatée, n'est-ce pas ?

et le compilo me crie "there are no arguments to 'degree'
that depend on a template parameter, so a declaration of
'degree' must be available"


Où ? C'est difficile à analyser un problème quand il n'y a pas
de contexte.

a chaque utilisation de degree dans d'autres fonctions de ma
classe A


C-à-d quelque chose du genre :

template< typename T >
class A
{
public:
void degree() { /* ... */ }
void f() {
degree() ;
}
} ;

? Ça ne pose pas de problèmes chez moi (avec g++ 4.1.0).

j'ai résolu le probleme en prefixant lesdits appels par "this->"


Typiquement, ce genre de problème se présente quand la fonction
en question est dans une classe de base qui dépend du template,
c-à-d :

template< typename T >
class B : public A< T > // avec A ci-dessus...
{
public:
void f()
{
degree() ;
}
} ;

Ici, le problème est simple : le compilateur divise tous les
symboles dans le template dans trois catégories : locaux au
template, dépendant et non-dépendant. Les premiers ne pose pas
de problème ; en général, c'est évident quels symboles y
appartiennent. Pour la reste, la répartition des symboles dans
l'une ou l'autre des catégories suit des règles établies par la
norme -- ici, degree est un symbole non-dépendant. Or, la
recherche et le binding des symboles non-dépendant a lieu
lorsque le compilateur lit la définition du template, avant la
moindre instantiation ; il ne peut prendre en compte alors que
des choses connues du compilateur à ce moment-là, et qui ne
dépendent nullement du paramètre du template. Alors, ici, la
classe de base dépend du template, et donc, elle n'entre pas en
ligne de compte ; le compilateur ne peut pas savoir qu'il y
aurait une fonction « degree » dans A<T> sans connaître T.

En préfixant l'appel par this->, tu as rendu le nom « degree »
dépendant. Ce qui fait que le compilateur ne le cherche pas tout
de suite. Et aussi qu'il suppose qu'il ne nomme pas un type,
parce que pour bien parser, il faut qu'il sache ce qui est type,
et ce qui ne l'est pas : si tu voulais accéder à un typedef dans
A<T>, il faudrait écrire quelque chose comme « typename
A<T>::Type ». (Le A<T>:: rend le nom dépendant aussi).

Néanmoins j'aimerai comprendre en quoi il y a difficulté pour
le compilo de remarquer que, templaté ou non, il existe bien
un symbole degree() dans A<T> ?


Il s'en rend compte, si il attend assez pour l'évaluer. C'est ce
qu'on appelle la récherche des noms en deux phases : il y a une
première phase lors de la définition du template, qui cherche
les noms non-dépendants, et une deuxième phase lors de
l'instantiation, qui cherche les noms dépendants (avec des
règles légèrement différentes dans les deux phases).
L'utilisation de this-> est un des moyens de le faire rétarder
la recherche... si « degree » prenait un paramètre de type T, il
le rétarderait aussi.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
meow
le compilateur ne peut pas savoir qu'il y
aurait une fonction « degree » dans A<T> sans connaître T.
Certes. :)


merci