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

récursion sur un membre template d'une class template

22 réponses
Avatar
AG
Bonjour,

Est-il seulement possible de faire ceci, et si oui comment (car ce code ne
compile pas)

Merci d'avance,

Alexandre.

#define N 20

template<class T> class A
{
public:
template<int D> void f(T *a);
};

template<class T> template<int D> void A<T>::f<D>(T *a)
{
int i;
for(i=0;i<9;i++)
a[i+1]+=a[i];
f<D-1>(a+10);
}

template<class T> template<> void A<T>::f<0>(T * a)
{
int i;
for(i=0;i<9;i++)
a[i+1]+=a[i];
}

int main()
{
A<int> monObjet;
int tab[N];
monObjet.f<1>(tab);
return 0;
}

10 réponses

1 2 3
Avatar
Michael DOUBEZ
Une autre approche est de faire de f une
fonction libre (et amie de A si necessaire).
ça m'intéresse. Une bonne simplification de ma class A est celle que

j'ai donnée :

template<class T> class A
{
public:
template<int D> void f(T * a);
};

et il me faut D-1 fonctions f() dans ma class A. Mon code C++ étant
réinterprété par un outil qui ne comprend que le mécanisme de
récursivité sur les fonctions templates, j'avais imaginé la solution
initialement proposée mais malheureusement impossible. La solution
"fonction helper" ainsi que celle que j'ai proposé en second lieu ne
conviennent pas car elles font usage de la récursivité sur les class
(et pas les fonctions). Je vais tenter la "fonction amie". Je
posterais ma solution si je suis bloqué et que j'ai besoin d'un coup
de main.



Au moment de poster j'ai eu une idée. Tu peux utiliser les typelist

class Null {};

template<int D>
struct vector_int
{
enum { value = D; }
typedef typename vector_int<D-1> next;
}

template<>
struct vector_int<0>
{
enum { value = 0; }
typedef Null next;
}

template<class T> class A
{

template<int D> f(T* a)
{
this->f(T* a,vector_int<D>());
}

private:
template<int D>
void f(T * a,vector_int<D>)
{
int i;
for(i=0;i<9;i++)
a[i+1]+=a[i];
this->f(a,vector_int<D>::next());
}

void f(T * a,Null)
{//do nothing
}

};

J'ai pas testé mais ça dois pas être loin de ce que tu veux.

Michael



Avatar
AG
En quoi la classe est necessaire et
la fonction f() utilise et travaille sur des membres de A.



template<class T, int D> void f(T* a);

ne conviens pas?
cf au-dessus, mais ta proposition ci-dessous est intéressante.


Est-ce que

template <class T> class A;
template <class T, int D> void f(T* a, A<T>& inst);
template <class T> class A
{
public:
friend template <int D> void f<T, D>(T* a, A<T>& inst);
};
ne conviendrait pas?
Si, mais mon outil n'aimera surement pas le A<T>& inst. Mais supposons que

cela suffise :

j'ai toujours besoin d'une récursion sur D.

template <class T, int D> void f<T,D>(T* a, A<T> &inst)
{
blabla;
f<T,D-1>(a+10,inst);
};

template<class T> void f<T,0>(T*a,A<T>&inst)
{
blabla;
};

ne fonctionne toujours pas, et je n'arrive pas à comprendre si ce que
j'essaie de faire correspond bien à ce que l'on appelle une "spécialisation
partielle" ou bien s'il s'agit de quelque chose d'autre. Je n'arrive pas non
plus à savoir si les spécialisations partielles de fonctions sont autorisées
ou pas (un des articles de GotW dit que c'est en cours de discussion, mais
il date un peu).
Et dans le standard....c'est un peu âpre à mon goût.

Avatar
AG
int main()
{
A<int,1> monObjet;
return 0;
}



int main()
{
int tab[100]={0};
A<int,1> monObjet;
monObject.f(tab);
return 0;
}

et ça ne compile plus... :-(

Avatar
Jean-Marc Bourguet
"AG" writes:

En quoi la classe est necessaire et
la fonction f() utilise et travaille sur des membres de A.



template<class T, int D> void f(T* a);

ne conviens pas?
cf au-dessus, mais ta proposition ci-dessous est intéressante.


Est-ce que

template <class T> class A;
template <class T, int D> void f(T* a, A<T>& inst);
template <class T> class A
{
public:
friend template <int D> void f<T, D>(T* a, A<T>& inst);
};
ne conviendrait pas?
Si, mais mon outil n'aimera surement pas le A<T>& inst. Mais supposons que

cela suffise :


J'oublie que c'est a faire passer sur un autre outil qu'un compilo. C'est
quoi les limitations de cet outil?

j'ai toujours besoin d'une récursion sur D.

template <class T, int D> void f<T,D>(T* a, A<T> &inst)
{
blabla;
f<T,D-1>(a+10,inst);
};

template<class T> void f<T,0>(T*a,A<T>&inst)
{
blabla;
};
ne fonctionne toujours pas, et je n'arrive pas à comprendre si ce que
j'essaie de faire correspond bien à ce que l'on appelle une "spécialisation
partielle" ou bien s'il s'agit de quelque chose d'autre. Je n'arrive pas non
plus à savoir si les spécialisations partielles de fonctions sont autorisées
ou pas (un des articles de GotW dit que c'est en cours de discussion, mais
il date un peu).
Et dans le standard....c'est un peu âpre à mon goût.


C'est une specialisation partielle et, de memoire, elles sont interdites
pour les fonctions. La technique habituelle pour circonvenir cette
limitation est d'utiliser la surcharge. Dans le cas present,

template <class T, int D> void f<T,D>(T* a, A<T> &inst)
{
blabla;
if (D > 1 )
f<T,D-1>(a+10,inst);
else
f<T>(a+10, inst);
};

template<class T> void f<T>(T*a,A<T>&inst)
{
blabla;
};

devrait donner une piste. Le test sur la valeur de D est un hack, mais il
ne devrait pas couter grand chose en temps d'execution.

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
Michael DOUBEZ
Une autre approche est de faire de f une
fonction libre (et amie de A si necessaire).
ça m'intéresse. Une bonne simplification de ma class A est celle que

j'ai donnée :

template<class T> class A
{
public:
template<int D> void f(T * a);
};

et il me faut D-1 fonctions f() dans ma class A. Mon code C++ étant
réinterprété par un outil qui ne comprend que le mécanisme de
récursivité sur les fonctions templates, j'avais imaginé la solution
initialement proposée mais malheureusement impossible. La solution
"fonction helper" ainsi que celle que j'ai proposé en second lieu ne
conviennent pas car elles font usage de la récursivité sur les class
(et pas les fonctions). Je vais tenter la "fonction amie". Je
posterais ma solution si je suis bloqué et que j'ai besoin d'un coup
de main.



Au moment de poster j'ai eu une idée. Tu peux utiliser les typelist
J'ai pas testé mais ça dois pas être loin de ce que tu veux.


Après test,un deplacement de typename (je m'y ferai jamais), le code
avec la typelist marche:

// Type indiquant la fin de la liste
class Null {};

//Définition récursive d'une liste d'entier - D doit être >=0
template<int D>
struct vector_int
{
enum { value = D };
typedef vector_int<D-1> next;
};

//terminaison à 0
template<>
struct vector_int<0>
{
enum { value = 0 };
typedef Null next;
};


template<class T>
class A
{
public:
//classe interface
template<int D> void f(T* a)
{
this->f(a,vector_int<D>());
}

private:
//cas général de la récursion
template<int D>
void f(T * a,vector_int<D>)
{
int i;
for(i=0;i<9;i++)
a[i+1]+=a[i];
this->f(a+10,typename vector_int<D>::next());
}

//fin de la récursion
void f(T * a,Null)
{//do nothing
}
};

Et voilà, tu as D fonctions membres appelées récursivement.

Michael




Avatar
AG
J'oublie que c'est a faire passer sur un autre outil qu'un compilo.
C'est
quoi les limitations de cet outil?


C'est un compilo C++ -> VHDL. Je ne vais pas re-écrire tout le manuel,
mais en gros il faut garder en tête que le résultat est du VHDL. Les
class, il ne connait pas, donc il met tout à plat. Le concept de
référence, il ne connait pas non plus, etc... Tout ce qui est template
est réutilisable à priori. La récursion n'est pas utilisable, sauf
dans le cadre des fonctions templates. Le pattern donné en exemple est
le classique :

template<int N> void f(void)
{
f<N-1>(void);
}
template<> void f<0>(void) // pour stopper la récursion.
{
}

sauf que dans mon cas, si j'ai d'autres arguments templates, la
spécialisation devient impossible. bref, je vais peut être devoir
revoir tout mon design.

C'est une specialisation partielle et, de memoire, elles sont
interdites
pour les fonctions. La technique habituelle pour circonvenir cette
limitation est d'utiliser la surcharge. Dans le cas present,

template <class T, int D> void f<T,D>(T* a, A<T> &inst)
{
blabla;
if (D > 1 )
f<T,D-1>(a+10,inst);
else
f<T>(a+10, inst);
};

template<class T> void f<T>(T*a,A<T>&inst)
{
blabla;
};

devrait donner une piste. Le test sur la valeur de D est un hack,
mais il
ne devrait pas couter grand chose en temps d'execution.
ok, alors j'ai corriger légèrement en :


template <class T, int D> void f(T* a, A<T> &inst)
{
blabla;
if (D > 1 )
f<T,D-1>(a+10,inst);
else
f<T>(a+10, inst);
};

template<class T> void f(T*a,A<T>&inst)
{
blabla;
};


mais ça ne compile toujours pas. la limite de profondeur des template
étant atteinte. La condition d'arrêt n'est visiblement pas prise en
compte.
AG.

Avatar
Michael DOUBEZ
devrait donner une piste. Le test sur la valeur de D est un hack,
mais il
ne devrait pas couter grand chose en temps d'execution.
ok, alors j'ai corriger légèrement en :


template <class T, int D> void f(T* a, A<T> &inst)
{
blabla;
if (D > 1 )
f<T,D-1>(a+10,inst);
else
f<T>(a+10, inst);
};
{snip]


mais ça ne compile toujours pas. la limite de profondeur des template
étant atteinte. La condition d'arrêt n'est visiblement pas prise en compte.


AMA, f<T,D-1>() est instancié même quand D<=1, ce qui créé une récursion
infinie.

Michael


Avatar
AG
AMA, f<T,D-1>() est instancié même quand D<=1, ce qui créé une
récursion infinie.
oui j'ai l'impression. Je vais jeter un coup d'oeil à ta proposition,

mais j'ai peur de me faire insulter par mon outil quand il lira ton
code :-)

Avatar
Jean-Marc Bourguet
"AG" writes:

J'oublie que c'est a faire passer sur un autre outil qu'un compilo. C'est
quoi les limitations de cet outil?


C'est un compilo C++ -> VHDL.


C'est du SystemC ou autre chose?

Je ne vais pas re-écrire tout le manuel, mais en gros il faut garder en
tête que le résultat est du VHDL. Les class, il ne connait pas, donc il
met tout à plat. Le concept de référence, il ne connait pas non plus,
etc... Tout ce qui est template est réutilisable à priori. La récursion
n'est pas utilisable, sauf dans le cadre des fonctions templates. Le
pattern donné en exemple est le classique :

template<int N> void f(void)
{
f<N-1>(void);
}
template<> void f<0>(void) // pour stopper la récursion.
{
}

sauf que dans mon cas, si j'ai d'autres arguments templates, la
spécialisation devient impossible. bref, je vais peut être devoir revoir
tout mon design.

C'est une specialisation partielle et, de memoire, elles sont interdites
pour les fonctions. La technique habituelle pour circonvenir cette
limitation est d'utiliser la surcharge. Dans le cas present,

template <class T, int D> void f<T,D>(T* a, A<T> &inst)
{
blabla;
if (D > 1 )
f<T,D-1>(a+10,inst);
else
f<T>(a+10, inst);
};

template<class T> void f<T>(T*a,A<T>&inst)
{
blabla;
};

devrait donner une piste. Le test sur la valeur de D est un hack, mais il
ne devrait pas couter grand chose en temps d'execution.
ok, alors j'ai corriger légèrement en :


template <class T, int D> void f(T* a, A<T> &inst)
{
blabla;
if (D > 1 )
f<T,D-1>(a+10,inst);
else
f<T>(a+10, inst);
};

template<class T> void f(T*a,A<T>&inst)
{
blabla;
};


mais ça ne compile toujours pas.


Je suis con.

Quand j'ai du temps je reflechirai a cela encore un peu.

--
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
Jean-Marc Bourguet
Michael DOUBEZ writes:

devrait donner une piste. Le test sur la valeur de D est un hack, mais
il
ne devrait pas couter grand chose en temps d'execution.
ok, alors j'ai corriger légèrement en :

template <class T, int D> void f(T* a, A<T> &inst)
{
blabla;
if (D > 1 )
f<T,D-1>(a+10,inst);
else
f<T>(a+10, inst);
};
{snip]
mais ça ne compile toujours pas. la limite de profondeur des template
étant atteinte. La condition d'arrêt n'est visiblement pas prise en
compte.


AMA, f<T,D-1>() est instancié même quand D<=1, ce qui créé une récursion
infinie.


C'est bien ce qui doit se passer.

--
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