Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 18/07/2007, à 09:55

Le Barde

[RÉSOLU] De la bonne utilisation des Templates.

Bonjour à tous,

Petit problème à la compilation de mon projet. Voici sans plus attendre la sortie du terminal :

adrien@adrien-portable:~/Documents/Travail/recherche/StageFlowShop/C++$ make
g++ -c -pipe -Wall -W -O2 -D_REENTRANT  -DQT_NO_DEBUG -DQT_THREAD_SUPPORT -DQT_SHARED -DQT_TABLET_SUPPORT -I/usr/share/qt3/mkspecs/default -I. -I/usr/include/qt3 -o BandB.o Flowshop/BandB/BandB.cpp
test -d Executable/ || mkdir -p Executable/
g++  -o Executable/Projet Application.o Atelier.o BandB.o ListeNoeuds.o Noeud.o Distrib.o Ordo.o Console.o Array.o    -L/usr/share/qt3/lib -L/usr/X11R6/lib -lqt-mt -lXext -lX11 -lm -lpthread
BandB.o: In function `BandB::Developpe()':
BandB.cpp:(.text+0x130): undefined reference to `Console<char*>::Afficher(char*)'
BandB.cpp:(.text+0x13b): undefined reference to `Console<int>::Afficher(int)'
BandB.cpp:(.text+0x147): undefined reference to `Console<char*>::Afficher(char*)'
BandB.cpp:(.text+0x159): undefined reference to `Console<int>::Afficher(int)'
Noeud.o: In function `Noeud::Evaluer()':
Noeud.cpp:(.text+0x4a): undefined reference to `BandB::probleme'
Noeud.cpp:(.text+0x81): undefined reference to `BandB::probleme'
Noeud.cpp:(.text+0xda): undefined reference to `BandB::probleme'
Noeud.cpp:(.text+0x11d): undefined reference to `BandB::probleme'
Noeud.o: In function `Noeud::Noeud(Noeud*, int)':
Noeud.cpp:(.text+0x1c0): undefined reference to `BandB::probleme'
Noeud.o:Noeud.cpp:(.text+0x1e3): more undefined references to `BandB::probleme' follow
Ordo.o: In function `Ordo::NEH()':
Ordo.cpp:(.text+0xd3d): undefined reference to `Array<double>::Sort(double*, int*)'
Ordo.cpp:(.text+0xd48): undefined reference to `Array<double>::Reverse(int*)'
Ordo.o: In function `Ordo::NEHameliore()':
Ordo.cpp:(.text+0xf52): undefined reference to `Array<double>::Sort(double*, int*)'
Ordo.cpp:(.text+0xf5d): undefined reference to `Array<double>::Reverse(int*)'
Ordo.o: In function `Ordo::Flowshop()':
Ordo.cpp:(.text+0x1084): undefined reference to `Console<double>::EnString(double)'
Ordo.cpp:(.text+0x10cd): undefined reference to `Console<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::Afficher(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
Ordo.cpp:(.text+0x112c): undefined reference to `Console<double>::EnString(double)'
Ordo.cpp:(.text+0x1198): undefined reference to `Console<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::Afficher(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
collect2: ld a retourné 1 code d'état d'exécution
make: *** [Executable/Projet] Erreur 1
adrien@adrien-portable:~/Documents/Travail/recherche/StageFlowShop/C++$

:arrow: Faut-il aussi initialiser les FONCTIONS membres statiques ?

Dernière modification par Le Barde (Le 18/07/2007, à 15:23)

Hors ligne

#2 Le 18/07/2007, à 13:03

Link31

Re : [RÉSOLU] De la bonne utilisation des Templates.

Les fonctions doivent être définies quelque part dans l'un des fichiers objet (*.o), et donc dans l'un des fichiers *.cpp. Si tu te contentes de mettre leur prototype dans un header *.h, ça ne risque pas de fonctionner. Il faut bien que leur code soit présent quelque part.

Si tu sais que ces fonctions seront présentes dans un *.o ou une bibliothèque mais que tu n'as pas accès à leur code, il faut les déclarer comme extern dans le header.

Hors ligne

#3 Le 18/07/2007, à 13:45

Le Barde

Re : [RÉSOLU] De la bonne utilisation des Templates.

Si si j'ai accès à leur code, c'est même moi qui les ai codées...

Hors ligne

#4 Le 18/07/2007, à 13:56

Link31

Re : [RÉSOLU] De la bonne utilisation des Templates.

Et ce code, il est dans quel fichier ?

Hors ligne

#5 Le 18/07/2007, à 14:03

Le Barde

Re : [RÉSOLU] De la bonne utilisation des Templates.

Alors il y a le BandB.cpp, que voici ci-dessous :

#include "../../Entrees-Sorties/Console.h"
#include "../Ordo.h"


BandB::BandB(Ordo* ordo)

		{

			// Initialisation de la recherche

			nbDev = 0; nbNoeud = 0;
			probleme = ordo;

			nbJob = probleme->reference->GetNbJob();

			nbMach = probleme->reference->GetNbMach();

			zopt = probleme->Resultat;

			racine = new Noeud(listeNoeuds);

			noeudOpt = racine;

			listeNoeuds = new ListeNoeuds(this);

			
			spij = new double*[nbJob]; // Initialisation du tableau à 2 dimensions spij.
			for (int a=0; a< nbMach+1 ; a++)
			{
				spij[a] = new double[nbMach];
			}
			

			// Calculs preliminaires pour l'evaluatioin des bornes

			for (int i=0; i<nbJob; i++)

				for (int j=0; j<nbMach; j++)

				{
					int jj;

					spij[i][j]=0;

					if (j<nbMach-1)

						for (jj=j+1; jj<nbMach; jj++)

							spij[i][j] += probleme->reference->Pij(i,jj);

				}

			

		}


void BandB::Developpe()

		{

			Noeud* noeudCourant = racine;



			while (noeudCourant)

			{
				int i;

				// Developpement du noeud courant

				nbDev++;

				for (i=0; i<nbJob - noeudCourant->niveau; i++)

				{

					noeudFils = new Noeud(noeudCourant, i);

					nbNoeud++;

					noeudFils->Evaluer();

					if (noeudFils->borneInf < zopt)

					{

						if (noeudFils->niveau<nbJob)

							listeNoeuds->PlacerEnTete(noeudFils);

						else

						{

							noeudOpt = noeudFils;

							zopt = noeudOpt->borneInf;

						}

					}

				}



				// Nouveau noeud à developper

				noeudCourant = NouveauNoeudCourant();



			}
			Consolechar::Afficher("Nb noeuds apparus: "); 
			Console<int>::Afficher(nbNoeud);

			Console<char*>::Afficher("\nNb noeuds developpes:");

			Console<int>::Afficher(nbDev);

		}



Noeud* BandB::NouveauNoeudCourant()

		{

			Noeud* noeudCourant;

			if (listeNoeuds->Length!=0)

			{

				// Extrait le premier element de la liste, à condition qu'il soit interessant

				noeudCourant = listeNoeuds->Premier();

				while ((noeudCourant)&&(noeudCourant->borneInf>zopt))

					noeudCourant = listeNoeuds->Premier();

			}

			else noeudCourant = NULL;

			return(noeudCourant);

		}

Dans la méthode BandB::Developpe(), j'utilise des méthodes statiques de classes instanciées du template Console. Voici le Console.h :

#ifndef Console_H
#define Console_H
#include <string> 

// Cette classe s'occupe des Entrées-sorties dans la console.

template <class TYPE>
class Console
{
	public:
	static void Afficher(TYPE Prompt);
	static std::string EnString(TYPE Transformazione);
	void AfficherBonjour();
};

class Consolechar:public Console<char*>
{
};

class Consoleint:public Console<int>
{};

class Consoledouble:public Console<double>
{};

//typedef Console<char*> Consolechar;
#endif

Et il y a le Console.cpp, dans lequel tout ce joli monde est implémenté :

#include "Console.h"

#include <iostream>
#include <string>
#include <sstream> 

//
// template<class TElement>
// Table<TElement>::Table(int n) {


template<typename TYPE> void Console<TYPE>::Afficher(TYPE Prompt)
{
	std::cout << Prompt;
}

template<typename TYPE> std::string Console<TYPE>::EnString(TYPE Transformazione)
{	
	// utiliser un flux de sortie pour créer la chaîne
   std::ostringstream oss;
  // écrire la valeur dans le flux
  oss << Transformazione;
  // renvoyer une string
  return oss.str();
}

template<typename TYPE> void Console<TYPE>::AfficherBonjour()
{
	std::cout << "Bonjour !\n";
}

... mais je ne comprends pas pourquoi il râle après

undefined reference to `Console<char*>::Afficher(char*)'

:'(

Hors ligne

#6 Le 18/07/2007, à 14:40

Link31

Re : [RÉSOLU] De la bonne utilisation des Templates.

Est-ce que ce n'est pas plutôt comme ça qu'on spécialise des classes templates ?

template <> class base_class <type>

Ce qui donnerait :

template <> class Console<char*>
{};
template <> class Console<int>
{};
template <> class Console<double>
{};

Il faut peut-être aussi spécialiser les fonctions dans Console.cpp.

Enfin, même si j'ai une bonne expérience de la programmation, je débute encore en C++, surtout quand il s'agit de templates...

Hors ligne

#7 Le 18/07/2007, à 14:48

Le Barde

Re : [RÉSOLU] De la bonne utilisation des Templates.

Ha, attends, c'est peut-être ça, mais j'ai un crack du C++ qui est passé pour m'aider à spécialiser ma classe Console. Hé mais justement, quand on spécialise une classe template il ne faut pas mettre le mot-clef template, non ? oO

Par contre, je viens de voir un truc sur la FAQ C++ de developpez.com... C'est épithète ça... Voyons voir...

* Se replonge dans son code. *

Hors ligne

#8 Le 18/07/2007, à 14:50

Link31

Re : [RÉSOLU] De la bonne utilisation des Templates.

Je ne vais pas courir le risque de me mesurer à un crack du C++ wink

Je suis juste allé voir là : http://www.cplusplus.com/doc/tutorial/templates.html

Hors ligne

#9 Le 18/07/2007, à 15:21

Le Barde

Re : [RÉSOLU] De la bonne utilisation des Templates.

Ah ben en fait voilà toute l'histoire :
1. Le problème est que je n'avais pas compris comment utiliser un template, et j'essayais de compiler le .cpp de ma classe générique (ce qui ne se fait donc absolument pas, hein, mais je viens de l'apprendre). J'ai donc renommé mon .cpp en .tpp et inclus le .tpp à la fin de mon .h.
Ensuite j'ai juste utilisé les classes comme je l'avais écrit, et ça marche.

2. Je viens de découvrir qu'on n'a pas besoin de déclarer une spécialisation d'une classe générique lorsqu'on veut utiliser une méthode static de celle-ci.
Ex : Pour ma classe Console, il me suffit d'appeler :

Console<MonTypeDeVariable>::Afficher(MaVariable);

3. J'ai vu ce qui est raconté sur la page web que tu viens de donner, et alors visilbement on n'est pas obligé de mettre

template <>

lorsqu'on spécialise une classe, enfin en tous cas g++ l'accepte visiblement...

Merci pour ton aide ! J'ai encore appris plein de choses big_smile

En espérant que ça pourra servir également...

Hors ligne