bonjour,
j'ai défini un patron de classe CVar<T> et je veux m'assurer que dans toutes
les implémentations, la classe T fournie en paramètre dérive d'une même
classe CTypeRoot.
Evidement, je peux vérifier que c'est bien le cas dans n'importe quel
constructeur.
Aussi je me suis dit : je vais introduire une donnée membre privée static
que j'initialise avec un appel de constructeur spécifique qui teste que
c'est le cas. Ce qui doit me permettre de détecter l'erreur au lancement du
programme, et pas à l'exécution (enfin, c'est mon but)
Mais avec mon compilateur, ça marche pas, ie la donnée membre static n'est
jamais initialisée...
Voilà le code simplifié :
/*export*/ template <class T>
class CVar : public CObjet
{
private :
inline CVar();
static CVar<T> *var_test; // ça ne marche pas
protected :
public :
inline CVar(const std::string&) ;
};
template <class T>
CVar<T> *CVar<T>::var_test=new CVar<T>::CVar<T>(); // initialisation de
le donnée membre static
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Anthony Fleury
bonjour,
Bonjour,
[...]
Mais avec mon compilateur, ça marche pas, ie la donnée membre static n'est jamais initialisée... Voilà le code simplifié :
/*export*/ template <class T> class CVar : public CObjet { private : inline CVar(); static CVar<T> *var_test; // ça ne marche pas protected : public : inline CVar(const std::string&) ; };
template <class T> CVar<T> *CVar<T>::var_test=new CVar<T>::CVar<T>(); // initialisation de le donnée membre static
Cette ligne compile avec le compilateur en question ? Parce que CVar<T>::CVar<T>() n'est pas un type.
Donc : template <class T> CVar<T> *CVar<T>::var_test = new CVar<T>;
Fonctionne chez moi et initialise bien une donnée membre static.
Est-ce que vous voyez où est l'erreur ? Quand j'exécute le programme, la donnée membre static n'est jamais initialisée....
Ca ne devrait pas compiler pour moi...
Par contre, est-ce un problème simplifié ou non ? En gros, y a-t-il un seul type CTypeRoot duquel toutes les classes T doivent dériver ? Si oui, pourquoi ne pas surcharger le constructeur de CVar pour le type CTypeRoot& (donc spécialisation du template), et refuser la construction dans le constructeur par défaut ?
-- Anthony Fleury
bonjour,
Bonjour,
[...]
Mais avec mon compilateur, ça marche pas, ie la donnée membre static n'est
jamais initialisée...
Voilà le code simplifié :
/*export*/ template <class T>
class CVar : public CObjet
{
private :
inline CVar();
static CVar<T> *var_test; // ça ne marche pas
protected :
public :
inline CVar(const std::string&) ;
};
template <class T>
CVar<T> *CVar<T>::var_test=new CVar<T>::CVar<T>(); // initialisation de
le donnée membre static
Cette ligne compile avec le compilateur en question ? Parce que
CVar<T>::CVar<T>() n'est pas un type.
Donc :
template <class T> CVar<T> *CVar<T>::var_test = new CVar<T>;
Fonctionne chez moi et initialise bien une donnée membre static.
Est-ce que vous voyez où est l'erreur ?
Quand j'exécute le programme, la donnée membre static n'est jamais
initialisée....
Ca ne devrait pas compiler pour moi...
Par contre, est-ce un problème simplifié ou non ? En gros, y a-t-il un
seul type CTypeRoot duquel toutes les classes T doivent dériver ? Si
oui, pourquoi ne pas surcharger le constructeur de CVar pour le type
CTypeRoot& (donc spécialisation du template), et refuser la construction
dans le constructeur par défaut ?
Mais avec mon compilateur, ça marche pas, ie la donnée membre static n'est jamais initialisée... Voilà le code simplifié :
/*export*/ template <class T> class CVar : public CObjet { private : inline CVar(); static CVar<T> *var_test; // ça ne marche pas protected : public : inline CVar(const std::string&) ; };
template <class T> CVar<T> *CVar<T>::var_test=new CVar<T>::CVar<T>(); // initialisation de le donnée membre static
Cette ligne compile avec le compilateur en question ? Parce que CVar<T>::CVar<T>() n'est pas un type.
Donc : template <class T> CVar<T> *CVar<T>::var_test = new CVar<T>;
Fonctionne chez moi et initialise bien une donnée membre static.
Est-ce que vous voyez où est l'erreur ? Quand j'exécute le programme, la donnée membre static n'est jamais initialisée....
Ca ne devrait pas compiler pour moi...
Par contre, est-ce un problème simplifié ou non ? En gros, y a-t-il un seul type CTypeRoot duquel toutes les classes T doivent dériver ? Si oui, pourquoi ne pas surcharger le constructeur de CVar pour le type CTypeRoot& (donc spécialisation du template), et refuser la construction dans le constructeur par défaut ?
-- Anthony Fleury
Eric Pruneau
"MGN" a écrit dans le message de news: 437adc9c$0$19713$
bonjour, j'ai défini un patron de classe CVar<T> et je veux m'assurer que dans toutes les implémentations, la classe T fournie en paramètre dérive d'une même classe CTypeRoot.
Donc tu veux vérifier que T hérite de CTypeRoot. Tu peux faire ce check au moment de la compilation. Donc si ce n'est pas le cas, ton programme ne compileras pas. Le livre Modern C++ Design de Andrei Alexandrescu donne la solution. Ce même auteur à développé Loki http://sourceforge.net/projects/loki-lib/
Tu y trouveras dans le fichier TypeManip.h tout ce qu'il te faut
La seule chose que tu as a faire est d'utiliser la macro: SUPERSUBCLASS(T,U) Cette macro retourne true si T est une base publique de U.
Maintenant tu peux utiliser le résultat avec un BOOST_STATIC_ASSERT http://www.boost.org/doc/html/boost_staticassert.html le même genre de méchanisme est aussi dans loki mais la doc de ce dernier lien est plus intéressante...
donc ton programme va ressembler à :
template <class T> class CVar : public CObjet { public: CVar() { BOOST_STATIC_ASSERT( SUPERSUBCLASS(CTypeRoot,T) ) ... } .... };
Voilà! Toute tentative d'utiliser le constructeur avec un T qui n'hérite pas de CTypeRoot produira un erreur de compilation!
Si tu n'en crois pas tes yeux, alors je te conseille le livre Modern C++ Desing
Eric
"MGN" <mgueguen@metrica.fr> a écrit dans le message de news:
437adc9c$0$19713$8fcfb975@news.wanadoo.fr...
bonjour,
j'ai défini un patron de classe CVar<T> et je veux m'assurer que dans
toutes les implémentations, la classe T fournie en paramètre dérive d'une
même classe CTypeRoot.
Donc tu veux vérifier que T hérite de CTypeRoot.
Tu peux faire ce check au moment de la compilation.
Donc si ce n'est pas le cas, ton programme ne compileras pas.
Le livre Modern C++ Design de Andrei Alexandrescu
donne la solution. Ce même auteur à développé Loki
http://sourceforge.net/projects/loki-lib/
Tu y trouveras dans le fichier TypeManip.h tout ce qu'il te faut
La seule chose que tu as a faire est d'utiliser la macro:
SUPERSUBCLASS(T,U)
Cette macro retourne true si T est une base publique de U.
Maintenant tu peux utiliser le résultat avec un BOOST_STATIC_ASSERT
http://www.boost.org/doc/html/boost_staticassert.html
le même genre de méchanisme est aussi dans loki mais la doc de ce dernier
lien
est plus intéressante...
donc ton programme va ressembler à :
template <class T>
class CVar : public CObjet
{
public:
CVar()
{
BOOST_STATIC_ASSERT( SUPERSUBCLASS(CTypeRoot,T) )
...
}
....
};
Voilà!
Toute tentative d'utiliser le constructeur avec un T qui n'hérite pas de
CTypeRoot produira un erreur de compilation!
Si tu n'en crois pas tes yeux, alors je te conseille le livre Modern C++
Desing
"MGN" a écrit dans le message de news: 437adc9c$0$19713$
bonjour, j'ai défini un patron de classe CVar<T> et je veux m'assurer que dans toutes les implémentations, la classe T fournie en paramètre dérive d'une même classe CTypeRoot.
Donc tu veux vérifier que T hérite de CTypeRoot. Tu peux faire ce check au moment de la compilation. Donc si ce n'est pas le cas, ton programme ne compileras pas. Le livre Modern C++ Design de Andrei Alexandrescu donne la solution. Ce même auteur à développé Loki http://sourceforge.net/projects/loki-lib/
Tu y trouveras dans le fichier TypeManip.h tout ce qu'il te faut
La seule chose que tu as a faire est d'utiliser la macro: SUPERSUBCLASS(T,U) Cette macro retourne true si T est une base publique de U.
Maintenant tu peux utiliser le résultat avec un BOOST_STATIC_ASSERT http://www.boost.org/doc/html/boost_staticassert.html le même genre de méchanisme est aussi dans loki mais la doc de ce dernier lien est plus intéressante...
donc ton programme va ressembler à :
template <class T> class CVar : public CObjet { public: CVar() { BOOST_STATIC_ASSERT( SUPERSUBCLASS(CTypeRoot,T) ) ... } .... };
Voilà! Toute tentative d'utiliser le constructeur avec un T qui n'hérite pas de CTypeRoot produira un erreur de compilation!
Si tu n'en crois pas tes yeux, alors je te conseille le livre Modern C++ Desing
Eric
MGN
Merci pour ta réponse. J'ai téléchargé loki et il me reste à étudier TypeManip.h Mais est-ce que tu comprends pourquoi mon code ne marche pas ? J'ai cru voir dans loki qu'il utilisait également une donnée membre static pour provoquer le test...
Marc
Merci pour ta réponse.
J'ai téléchargé loki et il me reste à étudier TypeManip.h
Mais est-ce que tu comprends pourquoi mon code ne marche pas ? J'ai cru voir
dans loki qu'il utilisait également une donnée membre static pour provoquer
le test...
Merci pour ta réponse. J'ai téléchargé loki et il me reste à étudier TypeManip.h Mais est-ce que tu comprends pourquoi mon code ne marche pas ? J'ai cru voir dans loki qu'il utilisait également une donnée membre static pour provoquer le test...
Marc
Anthony Fleury
bonjour,
Bonjour, J'avais déjà envoyé un article avec les choses que je vais noter ci dessous, mais j'ai annulé car la fin du message était fausse, et je ne comprend pas pourquoi, ca me fera l'occasion de poser une question dans la journée si je ne trouve pas.
Pour ce qui est des explications sur comment faire un contrôle de type, voir le post d'Eric Pruneau.
Mais avec mon compilateur, ça marche pas, ie la donnée membre static n'est jamais initialisée...
Quel est le compilateur en question ? Et le code ci-dessous est-il le vrai code compilé ? Car...
/*export*/ template <class T> class CVar : public CObjet { private : inline CVar(); static CVar<T> *var_test; // ça ne marche pas protected : public : inline CVar(const std::string&) ; };
template <class T> CVar<T> *CVar<T>::var_test=new CVar<T>::CVar<T>(); // initialisation de le donnée membre static
Ici ce code est invalide, car `CVar<T>::CVar<T>()` n'est pas un « type specifier ».
Avec : CVar<T> *CVar<T>::var_test=new CVar<T>;
Ca fonctionne.
Est-ce que vous voyez où est l'erreur ? Quand j'exécute le programme, la donnée membre static n'est jamais initialisée....
Comment est-ce vérifié ? à coup de gdb ?
Ici avec un code simplifié :
#include <iostream>
template <class T> class A { public: static A<T>* add; int a; A(int a = 0):a(a) { } };
template <class T> A<T>* A<T>::add = new A<T>(42);
int main() { std::cout << A< int >::add->a << std::endl; }
m'affiche bien 42 et ne provoque aucune erreur.
-- Anthony Fleury
bonjour,
Bonjour,
J'avais déjà envoyé un article avec les choses que je vais noter ci
dessous, mais j'ai annulé car la fin du message était fausse, et je ne
comprend pas pourquoi, ca me fera l'occasion de poser une question dans
la journée si je ne trouve pas.
Pour ce qui est des explications sur comment faire un contrôle de type,
voir le post d'Eric Pruneau.
Mais avec mon compilateur, ça marche pas, ie la donnée membre static n'est
jamais initialisée...
Quel est le compilateur en question ? Et le code ci-dessous est-il le
vrai code compilé ? Car...
/*export*/ template <class T>
class CVar : public CObjet
{
private :
inline CVar();
static CVar<T> *var_test; // ça ne marche pas
protected :
public :
inline CVar(const std::string&) ;
};
template <class T>
CVar<T> *CVar<T>::var_test=new CVar<T>::CVar<T>(); // initialisation de
le donnée membre static
Ici ce code est invalide, car `CVar<T>::CVar<T>()` n'est pas un « type
specifier ».
Avec :
CVar<T> *CVar<T>::var_test=new CVar<T>;
Ca fonctionne.
Est-ce que vous voyez où est l'erreur ?
Quand j'exécute le programme, la donnée membre static n'est jamais
initialisée....
Comment est-ce vérifié ? à coup de gdb ?
Ici avec un code simplifié :
#include <iostream>
template <class T>
class A {
public:
static A<T>* add;
int a;
A(int a = 0):a(a) { }
};
template <class T> A<T>* A<T>::add = new A<T>(42);
int main() {
std::cout << A< int >::add->a << std::endl;
}
Bonjour, J'avais déjà envoyé un article avec les choses que je vais noter ci dessous, mais j'ai annulé car la fin du message était fausse, et je ne comprend pas pourquoi, ca me fera l'occasion de poser une question dans la journée si je ne trouve pas.
Pour ce qui est des explications sur comment faire un contrôle de type, voir le post d'Eric Pruneau.
Mais avec mon compilateur, ça marche pas, ie la donnée membre static n'est jamais initialisée...
Quel est le compilateur en question ? Et le code ci-dessous est-il le vrai code compilé ? Car...
/*export*/ template <class T> class CVar : public CObjet { private : inline CVar(); static CVar<T> *var_test; // ça ne marche pas protected : public : inline CVar(const std::string&) ; };
template <class T> CVar<T> *CVar<T>::var_test=new CVar<T>::CVar<T>(); // initialisation de le donnée membre static
Ici ce code est invalide, car `CVar<T>::CVar<T>()` n'est pas un « type specifier ».
Avec : CVar<T> *CVar<T>::var_test=new CVar<T>;
Ca fonctionne.
Est-ce que vous voyez où est l'erreur ? Quand j'exécute le programme, la donnée membre static n'est jamais initialisée....
Comment est-ce vérifié ? à coup de gdb ?
Ici avec un code simplifié :
#include <iostream>
template <class T> class A { public: static A<T>* add; int a; A(int a = 0):a(a) { } };
template <class T> A<T>* A<T>::add = new A<T>(42);
int main() { std::cout << A< int >::add->a << std::endl; }
m'affiche bien 42 et ne provoque aucune erreur.
-- Anthony Fleury
Franck Branjonneau
"MGN" écrivait:
j'ai défini un patron de classe CVar<T> et je veux m'assurer que dans toutes les implémentations, la classe T fournie en paramètre dérive d'une même classe CTypeRoot.
Mais avec mon compilateur, ça marche pas, ie la donnée membre static n'est jamais initialisée...
/*export*/ template <class T> class CVar : public CObjet {
private :
inline CVar(); static CVar<T> *var_test; // ça ne marche pas
protected : public :
inline CVar(const std::string&) ;
};
template <class T> CVar<T> *CVar<T>::var_test=new CVar<T>::CVar<T>(); // initialisation de le donnée membre static
Pourquoi faire un dynamic_cast sur des pointeurs si c'est pour jeter une exception ?
Si exception il y a, tu espères l'attraper ?
Ta condition me semble inadéquate, je me trompes ?
Est-ce que vous voyez où est l'erreur ?
Si ta variable n'est pas initialisée c'est parce qu'elle n'est pas utilisée, c'est une particularité des templates.
-- Franck Branjonneau
"MGN" <mgueguen@metrica.fr> écrivait:
j'ai défini un patron de classe CVar<T> et je veux m'assurer que dans toutes
les implémentations, la classe T fournie en paramètre dérive d'une même
classe CTypeRoot.
Mais avec mon compilateur, ça marche pas, ie la donnée membre static n'est
jamais initialisée...
/*export*/ template <class T>
class CVar : public CObjet
{
private :
inline CVar();
static CVar<T> *var_test; // ça ne marche pas
protected :
public :
inline CVar(const std::string&) ;
};
template <class T>
CVar<T> *CVar<T>::var_test=new CVar<T>::CVar<T>(); // initialisation de
le donnée membre static
j'ai défini un patron de classe CVar<T> et je veux m'assurer que dans toutes les implémentations, la classe T fournie en paramètre dérive d'une même classe CTypeRoot.
Mais avec mon compilateur, ça marche pas, ie la donnée membre static n'est jamais initialisée...
/*export*/ template <class T> class CVar : public CObjet {
private :
inline CVar(); static CVar<T> *var_test; // ça ne marche pas
protected : public :
inline CVar(const std::string&) ;
};
template <class T> CVar<T> *CVar<T>::var_test=new CVar<T>::CVar<T>(); // initialisation de le donnée membre static
Pourquoi faire un dynamic_cast sur des pointeurs si c'est pour jeter une exception ?
Si exception il y a, tu espères l'attraper ?
Ta condition me semble inadéquate, je me trompes ?
Est-ce que vous voyez où est l'erreur ?
Si ta variable n'est pas initialisée c'est parce qu'elle n'est pas utilisée, c'est une particularité des templates.
-- Franck Branjonneau
kanze
Franck Branjonneau wrote:
"MGN" écrivait:
j'ai défini un patron de classe CVar<T> et je veux m'assurer que dans toutes template <class T> CVar<T> *CVar<T>::var_test=new CVar<T>::CVar<T>(); // initialisat ion de le donnée membre static
template <class T> inline CVar<T>::CVar() { if (!dynamic_cast<CTypeRoot*>(&T())) throw CException("problè me !");
Je ne l'avais pas remarqué avant, mais cette ligne ne doit pas se compiler. Si le template est instancié, en tout cas. L'expression « T() » est un rvalue ; on ne peut donc pas en prendre l'adresse. (Il y a une petite exception : si la classe T rédéfinit l'opérateur & unaire.)
}
Pourquoi faire un dynamic_cast sur des pointeurs si c'est pour jeter une exception ?
Si exception il y a, tu espères l'attraper ?
Ta condition me semble inadéquate, je me trompes ?
J'imagine que ce qu'il veut, c'est quelque chose come :
TypeRoot* p = static_cast< T* >( NULL ) ;
Si T ne dérive pas de TypeRoot, il y a une erreur de compilation.
Est-ce que vous voyez où est l'erreur ?
Si ta variable n'est pas initialisée c'est parce qu'elle n'est pas utilisée, c'est une particularité des templates.
Et si elle était utiliser, et donc instancié, il y aurait une erreur de compilation.
-- 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
Franck Branjonneau wrote:
"MGN" <mgueguen@metrica.fr> écrivait:
j'ai défini un patron de classe CVar<T> et je veux m'assurer que dans toutes
template <class T>
CVar<T> *CVar<T>::var_test=new CVar<T>::CVar<T>(); // initialisat ion de
le donnée membre static
template <class T>
inline CVar<T>::CVar()
{
if (!dynamic_cast<CTypeRoot*>(&T())) throw CException("problè me !");
Je ne l'avais pas remarqué avant, mais cette ligne ne doit pas
se compiler. Si le template est instancié, en tout cas.
L'expression « T() » est un rvalue ; on ne peut donc pas en
prendre l'adresse. (Il y a une petite exception : si la classe T
rédéfinit l'opérateur & unaire.)
}
Pourquoi faire un dynamic_cast sur des pointeurs si c'est pour
jeter une exception ?
Si exception il y a, tu espères l'attraper ?
Ta condition me semble inadéquate, je me trompes ?
J'imagine que ce qu'il veut, c'est quelque chose come :
TypeRoot* p = static_cast< T* >( NULL ) ;
Si T ne dérive pas de TypeRoot, il y a une erreur de
compilation.
Est-ce que vous voyez où est l'erreur ?
Si ta variable n'est pas initialisée c'est parce qu'elle n'est
pas utilisée, c'est une particularité des templates.
Et si elle était utiliser, et donc instancié, il y aurait une
erreur de compilation.
--
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
j'ai défini un patron de classe CVar<T> et je veux m'assurer que dans toutes template <class T> CVar<T> *CVar<T>::var_test=new CVar<T>::CVar<T>(); // initialisat ion de le donnée membre static
template <class T> inline CVar<T>::CVar() { if (!dynamic_cast<CTypeRoot*>(&T())) throw CException("problè me !");
Je ne l'avais pas remarqué avant, mais cette ligne ne doit pas se compiler. Si le template est instancié, en tout cas. L'expression « T() » est un rvalue ; on ne peut donc pas en prendre l'adresse. (Il y a une petite exception : si la classe T rédéfinit l'opérateur & unaire.)
}
Pourquoi faire un dynamic_cast sur des pointeurs si c'est pour jeter une exception ?
Si exception il y a, tu espères l'attraper ?
Ta condition me semble inadéquate, je me trompes ?
J'imagine que ce qu'il veut, c'est quelque chose come :
TypeRoot* p = static_cast< T* >( NULL ) ;
Si T ne dérive pas de TypeRoot, il y a une erreur de compilation.
Est-ce que vous voyez où est l'erreur ?
Si ta variable n'est pas initialisée c'est parce qu'elle n'est pas utilisée, c'est une particularité des templates.
Et si elle était utiliser, et donc instancié, il y aurait une erreur de compilation.
-- 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