Aide déboggage - template Fibonacci

Résolu/Fermé
Utilisateur anonyme - 3 mai 2013 à 07:20
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 - 5 mai 2013 à 13:10
Bonjour,
J'essaie d'écrire un programme qui calcule les indices de la suite de Fibonacci avec des templates. Ca marche d'ailleurs :

fibo.h :
#ifndef __FIBO_H__
#define __FIBO_H__
template <int i>
int fibo (void);
template <>
int fibo<0> ();
template <>
int fibo<1> ();
#include "fibo.impl.h"
#endif /* __FIBO_H__ */

fibo.impl.h :
#ifndef __FIBO_IMPL_H__
#define __FIBO_IMPL_H__
template <int i>
int fibo ()
{
return fibo<i-1>() + fibo<i-2>();
}
#endif /* __FIBO_IMPL_H__ */

fibo.cpp :
#include "fibo.h"
template <>
int fibo <0> ()
{
return 1;
}
template <>
int fibo <1> ()
{
return 1;
}

main.cpp :
#include <stdio.h>
#include <iostream>
#include "fibo.h"
int main (int /* argc */, char* /* argv */[])
{
const int i = 5;
std::cout << "l'indice " << i
<< " de la suite de Fibonacci est " << fibo<5>()
<< std::endl;
}

Là où ça coince, c'est que j'essaie d'écrire un programme qui calcule les indices de la suite de Fibonacci à partir d'un nombre passé à l'exécution. Je garde les mêmes fibo.h, fibo.impl.h et fibo.cpp et j'ajoute les fichiers suivants :

printFibo.h :
#ifndef __PRINTFIBO_H__
#define __PRINTFIBO_H__
template <int j>
void printFibo (const int i);
#include "printFibo.impl.h"
#endif /* __PRINTFIBO_H__ */

printFibo.impl.h :
#ifndef __PRINTFIBO_IMPL_H__
#define __PRINTFIBO_IMPL_H__
#include <stdio.h>
#include <iostream>
#include "fibo.h"
template <int j>
void printFibo (const int i)
{
std::cout << "l'indice " << j
<< " de la suite de Fibonacci est "
<< fibo<j>()
<< std::endl;
if (j < i) {
printFibo<j+1> (i);
}
}
#endif /* __PRINTFIBO_IMPL_H__ */

main.cpp:
#include <stdio.h>
#include <iostream>
#include "fibo.h"
#include "printFibo.h"
int main (int /* argc */, char* /* argv */[])
{
printFibo<0> (5);
}

Makefile :
CC=g++
CFLAGS=-W -Wall -ansi -pedantic
LDFLAGS=
EXECDIR=exec
EXEC=$(addprefix $(EXECDIR)/, fibo)
INCDIR=include
INCFLAGS=$(foreach d, $(INCDIR), -I$d)
SRCDIR=source
SRC=$(wildcard $(SRCDIR)/*.cpp)
OBJDIR=obj
OBJ=$(addprefix $(OBJDIR)/, $(notdir $(SRC:.cpp=.o)))
all: $(EXEC)
.PHONY: clean mrproper doc
clean:
@rm -rf $(OBJ)
mrproper: clean
@rm -rf $(EXEC)
doc:
@doxygen Doxyfile
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
@$(CC) -o $@ -c $< $(CFLAGS) $(INCFLAGS)
$(EXEC): $(OBJ)
@$(CC) -o $@ $^ $(LDFLAGS)

message d'erreur :
In file included from include/fibo.h:13:0,
from source/main.cpp:4:
include/fibo.impl.h:7:36: error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum) substituting `template<int i> int fibo() [with int i = 896]'
include/fibo.impl.h:7:36: required from `int fibo() [with int i = 898]'
include/printFibo.impl.h:17:9: recursively required from `void printFibo(int) [with int j = 1]'
include/printFibo.impl.h:17:9: required from `void printFibo(int) [with int j = 0]'
source/main.cpp:15:20: required from here

include/fibo.impl.h:7:36: error: no matching function for call to `fibo()'
include/fibo.impl.h:7:36: note: candidate is:
include/fibo.impl.h:5:5: note: template<int i> int fibo()
include/fibo.impl.h:5:5: note: substitution of deduced template arguments resulted in errors seen above
include/fibo.impl.h:7:36: error: no matching function for call to `fibo()'
include/fibo.impl.h:7:36: note: candidate is:
include/fibo.impl.h:5:5: note: template<int i> int fibo()
include/fibo.impl.h:5:5: note: template argument deduction/substitution failed:
In file included from include/printFibo.h:7:0,
from source/main.cpp:5:
include/printFibo.impl.h: In instantiation of `void printFibo(int) [with int j = 899]':
include/printFibo.impl.h:17:9: recursively required from `void printFibo(int) [with int j = 1]'
include/printFibo.impl.h:17:9: required from `void printFibo(int) [with int j = 0]'
source/main.cpp:15:20: required from here
include/printFibo.impl.h:12:5: error: no matching function for call to `fibo()'
include/printFibo.impl.h:12:5: note: candidate is:
In file included from include/fibo.h:13:0,
from source/main.cpp:4:
include/fibo.impl.h:5:5: note: template<int i> int fibo()
include/fibo.impl.h:5:5: note: template argument deduction/substitution failed:
In file included from include/printFibo.h:7:0,
from source/main.cpp:5:
include/printFibo.impl.h:12:5: error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum) instantiating `std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]'
include/printFibo.impl.h:17:9: recursively required from `void printFibo(int) [with int j = 1]'
include/printFibo.impl.h:17:9: required from `void printFibo(int) [with int j = 0]'
source/main.cpp:15:20: required from here

include/printFibo.impl.h:17:9: error: no matching function for call to `printFibo(const int&)'
include/printFibo.impl.h:17:9: note: candidate is:
include/printFibo.impl.h:10:6: note: template<int j> void printFibo(int)
include/printFibo.impl.h:10:6: note: template argument deduction/substitution failed:
In file included from include/fibo.h:13:0,
from source/main.cpp:4:
include/fibo.impl.h: In function `int fibo() [with int i = 898]':
include/fibo.impl.h:8:1: warning: control reaches end of non-void function [-Wreturn-type]
make: *** [obj/main.o] Erreur 1

Voilà. Si quelqu'un a une idée... Merci.
Marie

3 réponses

mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
Modifié par mamiemando le 4/05/2013 à 23:42
C'est normal, la résolution des templates se fait à la compilation, pas à l'exécution. Ce qu'il faut bien comprendre avec les templates, c'est qu'ils servent à déclarer des types "générique". Supposons que je déclare une liste qui dépende d'un paramètre template (la nature des élémetns listés). Alors si j'utilise list<int>, list<float>, list<mon_type_t> tout se passe comme si je compilais trois classes.

Dans le cas qui nous occupe les templates permettent (même si ce n'est pas un moyen très naturel) de résoudre le problème si l'entier est connu à la compilation. On va donc pour la valeur n = 3 engendrer la compilation de fibo<3>, fibo<2> et fibo<1>.

Maintenant si n est précisé à l'exécution, on est coincé, car on ne sait pas jusqu'à quelle profondeur d'imbrication il faut compiler. En d'autre termes, si la valeur de n n'est pas connue à la compilation, cette approche ne peut pas marcher.

Dans ton cas, si la suite doit être calculée en fonction d'un paramètre connu seulement à l'exécution il faut trouver une autre approche (par exemple une fonction récursive).

Bonne chance
0
Utilisateur anonyme
5 mai 2013 à 07:58
Je te remercie de ta réponse, mais tu as tort. Je me suis deboggee toute seule entretemps.

Pour avoir une fonction qui affiche une valeur template passée à l'exécution, il faut lui définir un maximum. Ma fonction printFibo devient :

Template <int i>
void printFibo (int j)
{
if (j>100) { return fibo<100>();}
(la même chose)
}

Et définir printFibo<100>.

Comme ça ça marche. Ce qui ne marche pas, c'est une fonction template sans maximum.

Cordialement,

Mare
0
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
5 mai 2013 à 13:10
Bonjour Marie,

Pas vraiment envie de rentrer dans un débat qui a tort et qui a raison, mais vu que ta solution ne marche que si n est inférieur à 100, ce n'est pas vraiment ce que j'appelle "marcher". Toutefois merci pour cette précision car je pensais pas que ce genre de solution pouvait marcher :-)

Ceci dit, garde en tête que les templates ne servent pas à traiter ce genre de problème. Donc on peut les utiliser pour résoudre le problème de manière un peu originale, dans la vraie vie on ne coderait pas une suite de Fibonacci comme cela.

Les templates récursifs sont par exemple correctement utilisés dans boost pour définir la méthode get<int i> pour récupérer le i-ème élément d'un tuple template.
https://stackoverflow.com/questions/7157210/boostbind-doesnt-work-with-boosttuplegetn

Bonne chance
0