// ERREUR
Contenu<int>& c =
static_cast<Contenu<int> >(mon_conteneur.get(0));
return 1;
}
Bien sûr, ça ne marche pas puisque je ne peux retrouver le type
d'origine. Je vois comment faire avec une alternative "dynamique",
mais en statique, je ne vois pas.
Je cherche à réaliser une classe Conteneur pour des objets Contenu avec des paramètres de template différents.
A présent, j'ai écrit ceci :
class Base{};
template <typename T> class Contenu : public Base {T t;};
class Conteneur { protected: std::vector<Base> objets; Ca n'ira pas : tu ne pourras inserer que des Bases et pas des Contenu.
Il faut que tu utilises std::vector<Base*> ou un pointeur intelligent sur Base*
public: template <typename T> void ajoute(T& b) {objets.push_back(b);} Ici il y a un problème : tu ajoutes un objet de type T à un conteneur de
Base Ou bien change le protype : void Ajoute( Base* b );
Base& get(int pos) {return objets[pos];} };
int main(int argv, char** argc) { Conteneur mon_conteneur; Contenu<int> mon_contenu; Base* mon_contenu = new Contenu<int>;
mon_conteneur.ajoute(mon_contenu);
// OK Base& b = mon_conteneur.get(0);
// ERREUR Contenu<int>& c > static_cast<Contenu<int> >(mon_conteneur.get(0));
return 1; }
Bien sûr, ça ne marche pas puisque je ne peux retrouver le type d'origine. Je vois comment faire avec une alternative "dynamique", mais en statique, je ne vois pas.
Merci.
Fred
Ces premières modifications devrait déjà te faire avancer
-- -------------------------------------------- Benoît Rousseau : roussebe at spray dot se Jouez en programmant : http://realtimebattle.sourceforge.net/
Frédéric Mayot wrote:
Bonjour,
Soit une classe template Contenu :
template <typename T>
class Contenu {T t;};
Je cherche à réaliser une classe Conteneur pour des objets Contenu avec
des paramètres de template différents.
A présent, j'ai écrit ceci :
class Base{};
template <typename T>
class Contenu : public Base {T t;};
class Conteneur
{
protected:
std::vector<Base> objets;
Ca n'ira pas : tu ne pourras inserer que des Bases et pas des Contenu.
Il faut que tu utilises std::vector<Base*> ou un pointeur intelligent
sur Base*
public:
template <typename T>
void ajoute(T& b) {objets.push_back(b);}
Ici il y a un problème : tu ajoutes un objet de type T à un conteneur de
Base
Ou bien change le protype : void Ajoute( Base* b );
Base& get(int pos) {return objets[pos];}
};
int main(int argv, char** argc)
{
Conteneur mon_conteneur;
Contenu<int> mon_contenu;
Base* mon_contenu = new Contenu<int>;
mon_conteneur.ajoute(mon_contenu);
// OK
Base& b = mon_conteneur.get(0);
// ERREUR
Contenu<int>& c > static_cast<Contenu<int> >(mon_conteneur.get(0));
return 1;
}
Bien sûr, ça ne marche pas puisque je ne peux retrouver le type
d'origine. Je vois comment faire avec une alternative "dynamique",
mais en statique, je ne vois pas.
Merci.
Fred
Ces premières modifications devrait déjà te faire avancer
--
--------------------------------------------
Benoît Rousseau : roussebe at spray dot se
Jouez en programmant : http://realtimebattle.sourceforge.net/
Je cherche à réaliser une classe Conteneur pour des objets Contenu avec des paramètres de template différents.
A présent, j'ai écrit ceci :
class Base{};
template <typename T> class Contenu : public Base {T t;};
class Conteneur { protected: std::vector<Base> objets; Ca n'ira pas : tu ne pourras inserer que des Bases et pas des Contenu.
Il faut que tu utilises std::vector<Base*> ou un pointeur intelligent sur Base*
public: template <typename T> void ajoute(T& b) {objets.push_back(b);} Ici il y a un problème : tu ajoutes un objet de type T à un conteneur de
Base Ou bien change le protype : void Ajoute( Base* b );
Base& get(int pos) {return objets[pos];} };
int main(int argv, char** argc) { Conteneur mon_conteneur; Contenu<int> mon_contenu; Base* mon_contenu = new Contenu<int>;
mon_conteneur.ajoute(mon_contenu);
// OK Base& b = mon_conteneur.get(0);
// ERREUR Contenu<int>& c > static_cast<Contenu<int> >(mon_conteneur.get(0));
return 1; }
Bien sûr, ça ne marche pas puisque je ne peux retrouver le type d'origine. Je vois comment faire avec une alternative "dynamique", mais en statique, je ne vois pas.
Merci.
Fred
Ces premières modifications devrait déjà te faire avancer
-- -------------------------------------------- Benoît Rousseau : roussebe at spray dot se Jouez en programmant : http://realtimebattle.sourceforge.net/
A la rigueur tu te fais ta propre fonction de cast qui fait un dynamic_cast + assert en debug et un static_cast en release.
Pas bête ça... C'est souvent utilisé ?
-------------------------------------------- Benoît Rousseau : roussebe at spray dot se Jouez en programmant : http://realtimebattle.sourceforge.net/
Vianney Lançon
Le Wed, 10 Dec 2003 10:43:18 +0100, dans fr.comp.lang.c++, Frédéric Mayot a dit :
Bonjour,
Soit une classe template Contenu :
| template <typename T> | class Contenu {T t;};
Je cherche à réaliser une classe Conteneur pour des objets Contenu avec des paramètres de template différents.
A présent, j'ai écrit ceci :
| | class Base{}; | | template <typename T> | class Contenu : public Base {T t;}; | | class Conteneur | { | protected:
// Bombe atomique sur le point d'exploser à la ligne du dessous. | std::vector<Base> objets; | public: | template <typename T> | void ajoute(T& b) {objets.push_back(b);} | Base& get(int pos) {return objets[pos];} | }; | | int main(int argv, char** argc) | { | Conteneur mon_conteneur; | Contenu<int> mon_contenu; | mon_conteneur.ajoute(mon_contenu); | | // OK | Base& b = mon_conteneur.get(0); | | // ERREUR /* | Contenu<int>& c | static_cast<Contenu<int> >(mon_conteneur.get(0)); */ Contenu<int>& c static_cast<Contenu<int>& >(mon_conteneur.get(0)); | | return 1; | } |
Perso je ferais un std::vector<Base*> objects et un get qui retourne un pointeur. Ce qui est facilitera le dynamic_cast (dans ce cas ajoute un destructeur virtuel dans Base). Au passage vérifies l'index passé. Par ce que la tu recopies un Contenu<int> dans un Base et comme sizof(Base) < sizeof(Contenu<int>) tu auras des problèmes.
A la rigueur tu te fais ta propre fonction de cast qui fait un dynamic_cast + assert en debug et un static_cast en release.
Enfin tu n'oublies pas dans ~Conteneur de libérer objects grâce par example à une fonction template. template <class StlContainer> void release_stl_ptr_container(StlContainer & container);
-- Vianney LANÇON radix omnia malorum prematurae optimisatia est -- Donald Knuth
Le Wed, 10 Dec 2003 10:43:18 +0100, dans fr.comp.lang.c++,
Frédéric Mayot a dit :
Bonjour,
Soit une classe template Contenu :
| template <typename T>
| class Contenu {T t;};
Je cherche à réaliser une classe Conteneur pour des objets Contenu avec
des paramètres de template différents.
A présent, j'ai écrit ceci :
|
| class Base{};
|
| template <typename T>
| class Contenu : public Base {T t;};
|
| class Conteneur
| {
| protected:
// Bombe atomique sur le point d'exploser à la ligne du dessous.
| std::vector<Base> objets;
| public:
| template <typename T>
| void ajoute(T& b) {objets.push_back(b);}
| Base& get(int pos) {return objets[pos];}
| };
|
| int main(int argv, char** argc)
| {
| Conteneur mon_conteneur;
| Contenu<int> mon_contenu;
| mon_conteneur.ajoute(mon_contenu);
|
| // OK
| Base& b = mon_conteneur.get(0);
|
| // ERREUR
/*
| Contenu<int>& c | static_cast<Contenu<int> >(mon_conteneur.get(0));
*/
Contenu<int>& c static_cast<Contenu<int>& >(mon_conteneur.get(0));
|
| return 1;
| }
|
Perso je ferais un std::vector<Base*> objects et un get qui retourne un
pointeur. Ce qui est facilitera le dynamic_cast (dans ce cas ajoute
un destructeur virtuel dans Base). Au passage vérifies l'index passé.
Par ce que la tu recopies un Contenu<int> dans un Base et
comme sizof(Base) < sizeof(Contenu<int>) tu auras des problèmes.
A la rigueur tu te fais ta propre fonction de cast qui fait un
dynamic_cast + assert en debug et un static_cast en release.
Enfin tu n'oublies pas dans ~Conteneur de libérer objects grâce
par example à une fonction template.
template <class StlContainer>
void release_stl_ptr_container(StlContainer & container);
--
Vianney LANÇON
radix omnia malorum prematurae optimisatia est
-- Donald Knuth
Le Wed, 10 Dec 2003 10:43:18 +0100, dans fr.comp.lang.c++, Frédéric Mayot a dit :
Bonjour,
Soit une classe template Contenu :
| template <typename T> | class Contenu {T t;};
Je cherche à réaliser une classe Conteneur pour des objets Contenu avec des paramètres de template différents.
A présent, j'ai écrit ceci :
| | class Base{}; | | template <typename T> | class Contenu : public Base {T t;}; | | class Conteneur | { | protected:
// Bombe atomique sur le point d'exploser à la ligne du dessous. | std::vector<Base> objets; | public: | template <typename T> | void ajoute(T& b) {objets.push_back(b);} | Base& get(int pos) {return objets[pos];} | }; | | int main(int argv, char** argc) | { | Conteneur mon_conteneur; | Contenu<int> mon_contenu; | mon_conteneur.ajoute(mon_contenu); | | // OK | Base& b = mon_conteneur.get(0); | | // ERREUR /* | Contenu<int>& c | static_cast<Contenu<int> >(mon_conteneur.get(0)); */ Contenu<int>& c static_cast<Contenu<int>& >(mon_conteneur.get(0)); | | return 1; | } |
Perso je ferais un std::vector<Base*> objects et un get qui retourne un pointeur. Ce qui est facilitera le dynamic_cast (dans ce cas ajoute un destructeur virtuel dans Base). Au passage vérifies l'index passé. Par ce que la tu recopies un Contenu<int> dans un Base et comme sizof(Base) < sizeof(Contenu<int>) tu auras des problèmes.
A la rigueur tu te fais ta propre fonction de cast qui fait un dynamic_cast + assert en debug et un static_cast en release.
Enfin tu n'oublies pas dans ~Conteneur de libérer objects grâce par example à une fonction template. template <class StlContainer> void release_stl_ptr_container(StlContainer & container);
-- Vianney LANÇON radix omnia malorum prematurae optimisatia est -- Donald Knuth
Frédéric Mayot
Vincent Lascaux wrote:
Quel est l'interet d'un tel conteneur ?
Appliquer des opérations sur tous les membres. Si j'ai une méthode Calcul dans Contenu, j'aurais par exemple Calcul_tout dans Conteneur qui fera une itération sur la collection et appelera la méthode Calcul de chaque objet Contenu.
Vincent Lascaux wrote:
Quel est l'interet d'un tel conteneur ?
Appliquer des opérations sur tous les membres. Si j'ai une méthode
Calcul dans Contenu, j'aurais par exemple Calcul_tout dans Conteneur qui
fera une itération sur la collection et appelera la méthode Calcul de
chaque objet Contenu.
Appliquer des opérations sur tous les membres. Si j'ai une méthode Calcul dans Contenu, j'aurais par exemple Calcul_tout dans Conteneur qui fera une itération sur la collection et appelera la méthode Calcul de chaque objet Contenu.
Frédéric Mayot
Perso je ferais un std::vector<Base*> objects et un get qui retourne un pointeur. Ce qui est facilitera le dynamic_cast (dans ce cas ajoute un destructeur virtuel dans Base).
Ca j'y avais pensé évidemment. Je voulais éviter des allocations dynamiques (au tout du moins, laisser cela à mon conteneur vector).
Par ce que la tu recopies un Contenu<int> dans un Base et comme sizof(Base) < sizeof(Contenu<int>) tu auras des problèmes.
C'est ce que je me suis dis aussi.
A la rigueur tu te fais ta propre fonction de cast qui fait un dynamic_cast + assert en debug et un static_cast en release.
Tu peux expliciter un peu, je ne te suis pas très bien...
Fred
Perso je ferais un std::vector<Base*> objects et un get qui retourne un
pointeur. Ce qui est facilitera le dynamic_cast (dans ce cas ajoute
un destructeur virtuel dans Base).
Ca j'y avais pensé évidemment. Je voulais éviter des allocations
dynamiques (au tout du moins, laisser cela à mon conteneur vector).
Par ce que la tu recopies un Contenu<int> dans un Base et
comme sizof(Base) < sizeof(Contenu<int>) tu auras des problèmes.
C'est ce que je me suis dis aussi.
A la rigueur tu te fais ta propre fonction de cast qui fait un
dynamic_cast + assert en debug et un static_cast en release.
Tu peux expliciter un peu, je ne te suis pas très bien...
Perso je ferais un std::vector<Base*> objects et un get qui retourne un pointeur. Ce qui est facilitera le dynamic_cast (dans ce cas ajoute un destructeur virtuel dans Base).
Ca j'y avais pensé évidemment. Je voulais éviter des allocations dynamiques (au tout du moins, laisser cela à mon conteneur vector).
Par ce que la tu recopies un Contenu<int> dans un Base et comme sizof(Base) < sizeof(Contenu<int>) tu auras des problèmes.
C'est ce que je me suis dis aussi.
A la rigueur tu te fais ta propre fonction de cast qui fait un dynamic_cast + assert en debug et un static_cast en release.
Tu peux expliciter un peu, je ne te suis pas très bien...
Fred
Vincent Lascaux
Appliquer des opérations sur tous les membres. Si j'ai une méthode Calcul dans Contenu, j'aurais par exemple Calcul_tout dans Conteneur qui fera une itération sur la collection et appelera la méthode Calcul de chaque objet Contenu.
Donc tout tes objets dérivent d'une classe de base, et tu n'as normalement pas trop de cast à faire...
-- Vincent
Appliquer des opérations sur tous les membres. Si j'ai une méthode
Calcul dans Contenu, j'aurais par exemple Calcul_tout dans Conteneur qui
fera une itération sur la collection et appelera la méthode Calcul de
chaque objet Contenu.
Donc tout tes objets dérivent d'une classe de base, et tu n'as normalement
pas trop de cast à faire...
Appliquer des opérations sur tous les membres. Si j'ai une méthode Calcul dans Contenu, j'aurais par exemple Calcul_tout dans Conteneur qui fera une itération sur la collection et appelera la méthode Calcul de chaque objet Contenu.
Donc tout tes objets dérivent d'une classe de base, et tu n'as normalement pas trop de cast à faire...
-- Vincent
Vianney Lançon
Le Wed, 10 Dec 2003 11:52:01 +0100, dans fr.comp.lang.c++, Frédéric Mayot a dit :
A la rigueur tu te fais ta propre fonction de cast qui fait un dynamic_cast + assert en debug et un static_cast en release.
Tu peux expliciter un peu, je ne te suis pas très bien...
Tu as une hierachie avec Base qui est abstrait ainsi que Derived1 et Derived2 qui sont concret et qui derive de Base. Et tu un containeur de Base* qui peuvent avoir pour type static soit Derived1 soit Derived2.
dynamic_cast<Derived1*>(base) retourne 0 si base a pour type static Derived2 sinon une addresse valide.
Mais cette operation prend un peu de temps (souvent négligeable).
Donc souvant les programeurs C font des casts plus ou moins sauvage en ce disant que comme il connaisse le type final cette étape est superflue.
Donc il font directement un static_cast.
La macro NDEBUG t'indique si tu es en mode debug. Tu peux donc optimiser les fonctions critiques.
-- Vianney LANÇON radix omnia malorum prematurae optimisatia est -- Donald Knuth
Le Wed, 10 Dec 2003 11:52:01 +0100, dans fr.comp.lang.c++,
Frédéric Mayot a dit :
A la rigueur tu te fais ta propre fonction de cast qui fait un
dynamic_cast + assert en debug et un static_cast en release.
Tu peux expliciter un peu, je ne te suis pas très bien...
Tu as une hierachie avec Base qui est abstrait ainsi que Derived1 et Derived2
qui sont concret et qui derive de Base.
Et tu un containeur de Base* qui peuvent avoir pour type static soit
Derived1 soit Derived2.
dynamic_cast<Derived1*>(base) retourne 0 si base a pour type static
Derived2 sinon une addresse valide.
Le Wed, 10 Dec 2003 11:52:01 +0100, dans fr.comp.lang.c++, Frédéric Mayot a dit :
A la rigueur tu te fais ta propre fonction de cast qui fait un dynamic_cast + assert en debug et un static_cast en release.
Tu peux expliciter un peu, je ne te suis pas très bien...
Tu as une hierachie avec Base qui est abstrait ainsi que Derived1 et Derived2 qui sont concret et qui derive de Base. Et tu un containeur de Base* qui peuvent avoir pour type static soit Derived1 soit Derived2.
dynamic_cast<Derived1*>(base) retourne 0 si base a pour type static Derived2 sinon une addresse valide.
Mais cette operation prend un peu de temps (souvent négligeable).
Donc souvant les programeurs C font des casts plus ou moins sauvage en ce disant que comme il connaisse le type final cette étape est superflue.
Donc il font directement un static_cast.
La macro NDEBUG t'indique si tu es en mode debug. Tu peux donc optimiser les fonctions critiques.
-- Vianney LANÇON radix omnia malorum prematurae optimisatia est -- Donald Knuth
Vianney Lançon
Le Wed, 10 Dec 2003 11:35:02 +0100, dans fr.comp.lang.c++, Benoit Rousseau a dit :
Vianney Lançon wrote:
A la rigueur tu te fais ta propre fonction de cast qui fait un dynamic_cast + assert en debug et un static_cast en release.
Pas bête ça... C'est souvent utilisé ?
Dans le milieu professionel? Ca dépend. un static_cast n'est pas strictement indentique à un static_cast (exemple héritages multiples, virtuels Et un professionnel n'aime pas que du code en release ait un comportement different du code en debug. Il est plus compliqué de trouver un bug qui ne se reproduit qu'en release. Et pour l'optimisation, il est plus rentable de se concenter sur les goulets d'etranglement.
Sur du code ou il y a déjà un static_cast ou un reinterpret_cast et que l'on a des complexes à mettre un dynamic_cast car on se dit que ça sert un rien. Tu ajoutes un petit down_cast<>(), tu obtiens alors un code plus robuste et tu perds tes complexes.
-- Vianney LANÇON radix omnia malorum prematurae optimisatia est -- Donald Knuth
Le Wed, 10 Dec 2003 11:35:02 +0100, dans fr.comp.lang.c++,
Benoit Rousseau a dit :
Vianney Lançon wrote:
A la rigueur tu te fais ta propre fonction de cast qui fait un
dynamic_cast + assert en debug et un static_cast en release.
Pas bête ça... C'est souvent utilisé ?
Dans le milieu professionel?
Ca dépend. un static_cast n'est pas strictement indentique
à un static_cast (exemple héritages multiples, virtuels
Et un professionnel n'aime pas que du code en release ait
un comportement different du code en debug. Il est plus compliqué
de trouver un bug qui ne se reproduit qu'en release.
Et pour l'optimisation, il est plus rentable de se concenter
sur les goulets d'etranglement.
Sur du code ou il y a déjà un static_cast ou un reinterpret_cast
et que l'on a des complexes à mettre un dynamic_cast car on se dit que
ça sert un rien.
Tu ajoutes un petit down_cast<>(), tu obtiens alors un code plus robuste
et tu perds tes complexes.
--
Vianney LANÇON
radix omnia malorum prematurae optimisatia est
-- Donald Knuth
Le Wed, 10 Dec 2003 11:35:02 +0100, dans fr.comp.lang.c++, Benoit Rousseau a dit :
Vianney Lançon wrote:
A la rigueur tu te fais ta propre fonction de cast qui fait un dynamic_cast + assert en debug et un static_cast en release.
Pas bête ça... C'est souvent utilisé ?
Dans le milieu professionel? Ca dépend. un static_cast n'est pas strictement indentique à un static_cast (exemple héritages multiples, virtuels Et un professionnel n'aime pas que du code en release ait un comportement different du code en debug. Il est plus compliqué de trouver un bug qui ne se reproduit qu'en release. Et pour l'optimisation, il est plus rentable de se concenter sur les goulets d'etranglement.
Sur du code ou il y a déjà un static_cast ou un reinterpret_cast et que l'on a des complexes à mettre un dynamic_cast car on se dit que ça sert un rien. Tu ajoutes un petit down_cast<>(), tu obtiens alors un code plus robuste et tu perds tes complexes.
-- Vianney LANÇON radix omnia malorum prematurae optimisatia est -- Donald Knuth
Marc Boyer
Frédéric Mayot wrote:
Bien sûr, ça ne marche pas puisque je ne peux retrouver le type d'origine. Je vois comment faire avec une alternative "dynamique", mais en statique, je ne vois pas.
Disons qu'il y a à mon humble avis un problème de conception. C++ est un système à typage statique, qui offre un certain polymorphisme dynamique à travers des références ou des pointeurs uniquement.
Vouloir mettre dans un conteneur STL des données de type différent sans utiliser de pointeur ou de référence, c'est comme vouloir planter une vis avec un clou. On doit pouvoir y arriver, mais à quel prix, et en se tapant souvent sur les doigts avant d'y arriver. Au fait, pourquoi ne pas faire un conteneur avec des références ? Le coût de l'indirection serait vraiment prohibitif ?
Marc Boyer -- Lying for having sex or lying for making war? Trust US presidents :-(
Frédéric Mayot wrote:
Bien sûr, ça ne marche pas puisque je ne peux retrouver le type
d'origine. Je vois comment faire avec une alternative "dynamique",
mais en statique, je ne vois pas.
Disons qu'il y a à mon humble avis un problème de
conception. C++ est un système à typage statique, qui
offre un certain polymorphisme dynamique à travers
des références ou des pointeurs uniquement.
Vouloir mettre dans un conteneur STL des données
de type différent sans utiliser de pointeur ou
de référence, c'est comme vouloir planter une vis
avec un clou. On doit pouvoir y arriver, mais à quel
prix, et en se tapant souvent sur les doigts avant
d'y arriver.
Au fait, pourquoi ne pas faire un conteneur avec
des références ? Le coût de l'indirection serait
vraiment prohibitif ?
Marc Boyer
--
Lying for having sex or lying for making war? Trust US presidents :-(
Bien sûr, ça ne marche pas puisque je ne peux retrouver le type d'origine. Je vois comment faire avec une alternative "dynamique", mais en statique, je ne vois pas.
Disons qu'il y a à mon humble avis un problème de conception. C++ est un système à typage statique, qui offre un certain polymorphisme dynamique à travers des références ou des pointeurs uniquement.
Vouloir mettre dans un conteneur STL des données de type différent sans utiliser de pointeur ou de référence, c'est comme vouloir planter une vis avec un clou. On doit pouvoir y arriver, mais à quel prix, et en se tapant souvent sur les doigts avant d'y arriver. Au fait, pourquoi ne pas faire un conteneur avec des références ? Le coût de l'indirection serait vraiment prohibitif ?
Marc Boyer -- Lying for having sex or lying for making war? Trust US presidents :-(