OVH Cloud OVH Cloud

template et attribut static

3 réponses
Avatar
aVrama
Bonjour,
J'effectue le portage c++, sous eCos, d'une application compilé en GCC
2.95 vers le gcc 3.4.1. J'ai des erreurs de conception que je n'arrive
pas à expliquer. Voici mes fichiers (extrait) et l'erreur:

Fichier ObjectList.h
--------------------
namespace Meta
{
template <class T>
class TObjectList : public ObjectList
{
public:
typedef typename TLS::LG::LM<T>::iterator listIterator;

listIterator beginList() { return m_list.begin(); }
listIterator endList() { return m_list.end(); }
unsigned int nbObject() {return m_list.count();}
...
protected:

static TObjectList<T> *m_Instance;

private:
...
};
}

Je désire initialiser m_Instance à null:
Fichier testQ.cpp
-----------------
1 #include "testQ.h"
2 #include "ObjectList.h"

...
25 Meta::TObjectList<testQ> *Meta::TObjectList<testQ>::m_Instance
= NULL;
...


Lorque je compile avec le gcc 3.4.1, j'ai l'erreur suivante:
-> testQ.cpp(25): error: too few template-parameter-lists
-> testQ.cpp(25): error: expected `,' or `;' before '=' token

J'ai essayé de déplacer le pointeur '*':
Meta::TObjectList<testQ> Meta::TObjectList<testQ>::*m_Instance = NULL;
et la j'ai une erreur au link (erreur de conception ?):
-> testQ.cpp:39: multiple definition of `m_Instance'
-> CSM.cpp:34: first defined here

Est-ce que quelqu'un peut m'expliquer ce qui se passe?
Merci d'avance pour votre aide,
aVr

3 réponses

Avatar
Lahsen
Bonjour,
J'effectue le portage c++, sous eCos, d'une application compilé en GCC
2.95 vers le gcc 3.4.1. J'ai des erreurs de conception que je n'arrive
pas à expliquer. Voici mes fichiers (extrait) et l'erreur:

Fichier ObjectList.h
--------------------
namespace Meta
{
template <class T>
class TObjectList : public ObjectList
{
public:
typedef typename TLS::LG::LM<T>::iterator listIterator;

listIterator beginList() { return m_list.begin(); }
listIterator endList() { return m_list.end(); }
unsigned int nbObject() {return m_list.count();}
...
protected:

static TObjectList<T> *m_Instance;

private:
...
};
}

Je désire initialiser m_Instance à null:
Fichier testQ.cpp
-----------------
1 #include "testQ.h"
2 #include "ObjectList.h"

...
25 Meta::TObjectList<testQ> *Meta::TObjectList<testQ>::m_Instance
= NULL;
...


Lorque je compile avec le gcc 3.4.1, j'ai l'erreur suivante:
-> testQ.cpp(25): error: too few template-parameter-lists
-> testQ.cpp(25): error: expected `,' or `;' before '=' token

J'ai essayé de déplacer le pointeur '*':
Meta::TObjectList<testQ> Meta::TObjectList<testQ>::*m_Instance = NULL;
et la j'ai une erreur au link (erreur de conception ?):
-> testQ.cpp:39: multiple definition of `m_Instance'
-> CSM.cpp:34: first defined here

Est-ce que quelqu'un peut m'expliquer ce qui se passe?
Merci d'avance pour votre aide,
aVr


using namespace Meta;

template <testQ>
TObjectList<testQ> *TObjectList<testQ>::m_Instance(NULL);

Lors de la définition d'un membre static d'un modèle, on doit précéder
la spécialisation du modèle pour le type nomType, par:
template <nomType>

Avatar
James Kanze
aVrama wrote:

J'effectue le portage c++, sous eCos, d'une application
compilé en GCC 2.95 vers le gcc 3.4.1. J'ai des erreurs de
conception que je n'arrive pas à expliquer. Voici mes fichiers
(extrait) et l'erreur:

Fichier ObjectList.h
--------------------
namespace Meta
{
template <class T>
class TObjectList : public ObjectList
{
public:
typedef typename TLS::LG::LM<T>::iterator listIterator;

listIterator beginList() { return m_list.begin(); }
listIterator endList() { return m_list.end(); }
unsigned int nbObject() {return m_list.count();}
...
protected:

static TObjectList<T> *m_Instance;

private:
...
};


Est-ce que tu ne voudrais pas fournir une définition de
m_Instance ? Techniquement, au moins, sans la définition, tu as
un comportement indéfini. Quelque chose du genre :

template< typename T >
TObjectList< T > TObjectList< T >::m_instance = NULL ;

par exemple. (L'initialisation est optionelle, je crois.) Sinon,
il faudrait fournir une définition explicite pour chaque
instantiation du template.

}

Je désire initialiser m_Instance à null:
Fichier testQ.cpp
-----------------
1 #include "testQ.h"
2 #include "ObjectList.h"

...
25 Meta::TObjectList<testQ> *Meta::TObjectList<testQ>::m_Instance
= NULL;
...


Question : est-ce que tu veux une spécialisation explicite
ici ? C-à-d une définition qui est propre à la spécialisation
du type testQ, et qui ne vaut que pour cette spécialisation ?
Si oui, il faudrait dire au compilateur que c'est une
spécialisation explicite, c-à-d :

template<>
Meta::TObjectList< testQ >*
Meta::TObjectList< testQ >::m_Instance = NULL ;

(Note aussi que dans ce cas-ci, l'initialisation est
obligatoire ; sinon, ce n'est qu'une déclaration.)

Aussi, si tu veux une telle spécialisation, il faudrait
s'assurer que la définition se trouve dans une seule unité de
compilation, mais qu'il y a bien une déclaration (la même chose,
sans l'initialisation) dans toutes les unités de compilation où
il y a risque d'une instantiation implicite du template.

Sinon, je te conseille de mettre la définition dans l'en-tête,
de la même façon que tu mets les définitions des fonctions
membre dans l'en-tête. (Au moins, évidemment, que ton
compilateur supporte export. Mais ce n'est pas le cas de g++.)

Lorque je compile avec le gcc 3.4.1, j'ai l'erreur suivante:
-> testQ.cpp(25): error: too few template-parameter-lists
-> testQ.cpp(25): error: expected `,' or `;' before '=' token


Je ne sais pas trop interpréter son message d'erreur, mais le
problème, sans doute, c'est qu'il ne sait pas qu'il s'agit d'une
spécialisation de template, et qu'il essaie donc de
l'interpréter comme quelque chose d'autre.

L'implémentation des templates dans CFront reconnaissait les
spécialisations explicites simplement d'après la syntaxe, et une
spécialisation explicite n'importe où suffisait pour inhiber la
spécialisation implicite. C'était une particularité de cette
implémentation, je crois ; à l'époque, il manquait une
définition claire de ce qu'il fallait, et chaque compilateur
faisait ce qu'il voulait. Mais l'influence de CFront, surtout
dans le monde Unix, a été énorme, et j'imagine que beaucoup de
compilateurs ont continué à supporter ses caprices bien après sa
disparition.

J'ai essayé de déplacer le pointeur '*':
Meta::TObjectList<testQ> Meta::TObjectList<testQ>::*m_Instance = NULL;


Et pourquoi ? Ici, il s'agirait d'un pointeur à membre, ce qui
n'est certainement pas ce que tu veux.

et la j'ai une erreur au link (erreur de conception ?):
-> testQ.cpp:39: multiple definition of `m_Instance'
-> CSM.cpp:34: first defined here


Ce qui fait penser que g++ définit implicitement la variable
statique, même sans la définition. Je ne crois pas que ce soit
un comportement exigé par la norme.

--
James Kanze (GABI Software) email:
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
James Kanze
Lahsen wrote:

J'effectue le portage c++, sous eCos, d'une application
compilé en GCC 2.95 vers le gcc 3.4.1. J'ai des erreurs de
conception que je n'arrive pas à expliquer. Voici mes
fichiers (extrait) et l'erreur:

Fichier ObjectList.h
--------------------
namespace Meta
{
template <class T>
class TObjectList : public ObjectList
{
public:
typedef typename TLS::LG::LM<T>::iterator listIterator;

listIterator beginList() { return m_list.begin(); }
listIterator endList() { return m_list.end(); }
unsigned int nbObject() {return m_list.count();}
...
protected:

static TObjectList<T> *m_Instance;

private:
...
};
}

Je désire initialiser m_Instance à null:
Fichier testQ.cpp
-----------------
1 #include "testQ.h"
2 #include "ObjectList.h"

...
25 Meta::TObjectList<testQ> *Meta::TObjectList<testQ>::m_Instance
= NULL;
...

Lorque je compile avec le gcc 3.4.1, j'ai l'erreur suivante:
-> testQ.cpp(25): error: too few template-parameter-lists
-> testQ.cpp(25): error: expected `,' or `;' before '=' token

J'ai essayé de déplacer le pointeur '*':
Meta::TObjectList<testQ> Meta::TObjectList<testQ>::*m_Instance = NULL;
et la j'ai une erreur au link (erreur de conception ?):
-> testQ.cpp:39: multiple definition of `m_Instance'
-> CSM.cpp:34: first defined here

Est-ce que quelqu'un peut m'expliquer ce qui se passe?
Merci d'avance pour votre aide,
aVr


using namespace Meta;

template <testQ>
TObjectList<testQ> *TObjectList<testQ>::m_Instance(NULL);

Lors de la définition d'un membre static d'un modèle, on doit
précéder la spécialisation du modèle pour le type nomType,
par: template <nomType>


? Je ne comprends pas trop ce que tu essaies de faire ici, mais
autant que je sache, il n'y a nulle part dans le langage où on a
la syntaxe : « template< nomType > ». Pour définir une
variable membre statique d'un template, de façon générique,
c'est :

template< typename T >
TObjectList< T >* TObjectList< T >::m_Instance = NULL ;

Pour une spécialisation explicite, c'est :

template<>
TObjectList< testQ >* TObjectList< testQ >::m_Instance = NULL ;

Ce sont les deux syntaxes que je connais qui concerne les
variables statiques membres d'une classe générique.

--
James Kanze (GABI Software) email:
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