OVH Cloud OVH Cloud

template & contaner STL

8 réponses
Avatar
sentenza
bonjour,

il me faut creer une class qui puisse gerer plusieurs type de container
de la lib STL (stack, vector, et map).
Je dois implementer les methodes :
- Push(val) : ajoute un element en haut de la pile.
- Pop() : enleve le premier element de la pile.
- Add() : additionne tous les elements de la pile
- Sub(), ...

mon probleme est comment gerer les different container STL dans une class.

J'ai essaye de declarer une variable privee template qui puisse contenir
n'importe quel type de container :

template<class T>
class MaClass
{
private :
<T<int>> _ma_pile;

};

mais le compilo n'apprecie pas trop :-(

existe t'il une maniere de faire une class poly-container ?

meci d'avance

--
char sentenza9[] =
"\xeb\x0d\x5f\x31\xc0\x50\x89\xe2"
"\x52\x57\x54\xb0\x3b\xcd\x80\xe8"
"\xee\xff\xff\xff/bin/sh";

8 réponses

Avatar
Luc Hermitte
sentenza wrote in
news:3fd5817f$0$6972$:

il me faut creer une class qui puisse gerer plusieurs type de
container de la lib STL (stack, vector, et map).
Je dois implementer les methodes :
- Push(val) : ajoute un element en haut de la pile.


Aucun sens pour un std::map

- Pop() : enleve le premier element de la pile.


Voir remarque précédente

- Add() : additionne tous les elements de la pile
- Sub(), ...


std::transform, std::accumulate ou std::for_each ?

mon probleme est comment gerer les different container STL dans une
class.

J'ai essaye de declarer une variable privee template qui puisse
contenir n'importe quel type de container :

template<class T>
class MaClass
{
private :
<T<int>> _ma_pile;

};

mais le compilo n'apprecie pas trop :-(


Si je me souviens bien :
template <class <typename> C, typename E >
class TaClasse {
C<E> ta_pile_;
public:
...
};

Par contre, tous les compilateurs ne supportent pas cette écriture.

existe t'il une maniere de faire une class poly-container ?


C'est loin d'être un problème simple. Tous les containers sont loins
d'être équivalents -- par rapport aux fonctions qu'ils proposent, leur
mode de fonctionnement, ... et surtout leur raison d'être.
Tu seras très certainement interressé par le second Item traité dans
"Effective STL" (par Scott Meyers, publié chez Addisson Wesley) qui
s'intitule justement "Beware the illusion of container-independent code".

Parmi les approches qui restent le plus container-independant, il y a les
algorithmes de la STL qui itèrent sur des plages d'éléments.

--
Luc Hermitte <hermitte at free.fr>
FAQ de <news:fr.comp.lang.c++> :
<http://www.cmla.ens-cachan.fr/Utilisateurs/dosreis/C++/FAQ/>
Dejanews : <http://groups.google.com/advanced_group_search>

Avatar
Benoit Rousseau
sentenza wrote:
bonjour,

il me faut creer une class qui puisse gerer plusieurs type de container
de la lib STL (stack, vector, et map).
Je dois implementer les methodes :
- Push(val) : ajoute un element en haut de la pile.
- Pop() : enleve le premier element de la pile.
- Add() : additionne tous les elements de la pile
- Sub(), ...

[...]

mais le compilo n'apprecie pas trop :-(

existe t'il une maniere de faire une class poly-container ?
Je ne crois pas...

Par contre, tu peux créer un type de base virtuel, et en faire dériver
un template qui sera spécialisé (je ne sais pas si spécialisé est le
terme à employer) pour chaque type :

class BaseType {
public:
virtual ~BaseType () {};
};

template< class T > Type : public BaseType {
public:
Type( const T& t ) : value( t ) {}
T& get_value() { return value; }
protected:
T value;
}

et ton container : stack< BaseType* >
Il y aura surement un problème à l'addition par contre !!! Mais je ne
sais pas comment tu comptais le résoudre avec ton système précedent.


--
--------------------------------------------
Benoît Rousseau : roussebe at spray dot se
Jouez en programmant : http://realtimebattle.sourceforge.net/

Avatar
Vianney Lançon
Le Tue, 09 Dec 2003 11:15:58 +0100, dans fr.comp.lang.c++,
Luc Hermitte a dit :
sentenza wrote in
news:3fd5817f$0$6972$:

il me faut creer une class qui puisse gerer plusieurs type de
container de la lib STL (stack, vector, et map).
Je dois implementer les methodes :
- Push(val) : ajoute un element en haut de la pile.
- Pop() : enleve le premier element de la pile.
- Add() : additionne tous les elements de la pile
- Sub(), ...
mon probleme est comment gerer les different container STL dans une
class.


template <class <typename> C, typename E >
class TaClasse {
C<E> ta_pile_;
public:
...
};

Par contre, tous les compilateurs ne supportent pas cette écriture.

existe t'il une maniere de faire une class poly-container ?


C'est loin d'être un problème simple. Tous les containers sont loins
d'être équivalents -- par rapport aux fonctions qu'ils proposent, leur
mode de fonctionnement, ... et surtout leur raison d'être.
Tu seras très certainement interressé par le second Item traité dans
"Effective STL" (par Scott Meyers, publié chez Addisson Wesley) qui
s'intitule justement "Beware the illusion of container-independent code".

Parmi les approches qui restent le plus container-independant, il y a les
algorithmes de la STL qui itèrent sur des plages d'éléments.



Tu fait une template qui agrège un containeur de la stl. Tu fait de la
specialisation partiel pour certains types qui posent des problèmes.
Ou tu crees d'autres classes spécialisées.

Et tu fait tout dériver d'une même interface.

Ensuite tu travailles uniquement avec une enveloppe.

tmplatee <typename T>
class Container
{
public:
virtual void Add(const T & value) = 0;
virtual void Sub(const T & value) = 0;
virtual void Pop() = 0;
};

template<typename ContainerType>
class StlAdaptor : public Container<typename ContainerType::value_type>
{
public:
typedef typename ContainerType::value_type ValueType;
public:
explicit StlAdaptor(ContainerType* container):m_container(container){}
virtual void Add(const ValueType & value) { m_container->push_back(value); }
virtual void Sub(const ValueType & value) {
typename ContainerType::iterator it = find(m_container->begin(),
m_container->end(), value);
if (it != m_container->end()) m_container->erase(it);
}
virtual void Pop() { m_container->pop_back();}
private:
ContainerType* m_container;
};

template<typename ContainerType>
class StlAdaptorSet
: public Container<typename ContainerType::value_type>
{
public:
typedef typename ContainerType::value_type ValueType;
public:
explicit StlAdaptorSet(ContainerType* container):m_container(container){}
virtual void Add(const ValueType & value) { m_container->insert(value); }
virtual void Sub(const ValueType & value) {
typename ContainerType::iterator it = find(m_container->begin(),
m_container->end(), value);
if (it != m_container->end()) m_container->erase(it);
}
virtual void Pop() { assert(0 && "not implemented"); }
private:
ContainerType* m_container;
};


template<typename T>
class MaClass
{
public:
explicit MaClass(std::list<T> * stlContainer)
:m_container(new StlAdaptor< std::list<T> >(stlContainer)){ }

explicit MaClass(std::set<T> * stlContainer)
:m_container(new StlAdaptorSet< std::set<T> >(stlContainer)){ }

explicit MaClass(std::vector<T> * stlContainer)
:m_container(new StlAdaptor< std::vector<T> >(stlContainer)){ }

void Add(const T & value) { m_container->Add(value); }
void Sub(const T & value) { m_container->Sub(value); }
void Pop() { m_container->Pop(); }
private:
std::auto_ptr< Container<T> > m_container;
};

void test()
{

std::vector<int> v;
std::list<int> l;
std::set<int> s;

MaClass<int> a(&v);
MaClass<int> b(&l);
MaClass<int> c(&s);
std::list<MaClass<int>*> maClassList;
std::for_each(maClassList.begin(), maClassList.end(),
std::bind2nd(std::mem_fun(&MaClass<int>::Add), 4));

}






--
Vianney LANÇON
radix omnia malorum prematurae optimisatia est
-- Donald Knuth


Avatar
Vianney Lançon
Le Tue, 09 Dec 2003 09:01:02 +0100, dans fr.comp.lang.c++,
sentenza a dit :

template<class T>
class MaClass
{
private :
<T<int>> _ma_pile;

};


template<class Container>
class MaClass
{
public:
typedef typename Container::value_Type ValueType;
public
void Add(typename Container::value_type &);
private :
Container _ma_pile;
};

Et tu spepecialises.



--
Vianney LANÇON
radix omnia malorum prematurae optimisatia est
-- Donald Knuth

Avatar
sentenza
Luc Hermitte wrote:
sentenza wrote in
news:3fd5817f$0$6972$:


il me faut creer une class qui puisse gerer plusieurs type de
container de la lib STL (stack, vector, et map).
Je dois implementer les methodes :
- Push(val) : ajoute un element en haut de la pile.



Aucun sens pour un std::map


- Pop() : enleve le premier element de la pile.



Voir remarque précédente


- Add() : additionne tous les elements de la pile
- Sub(), ...



std::transform, std::accumulate ou std::for_each ?


mon probleme est comment gerer les different container STL dans une
class.

J'ai essaye de declarer une variable privee template qui puisse
contenir n'importe quel type de container :

template<class T>
class MaClass
{
private :
<T<int>> _ma_pile;

};

mais le compilo n'apprecie pas trop :-(



Si je me souviens bien :
template <class <typename> C, typename E >
class TaClasse {
C<E> ta_pile_;
public:
...
};

Par contre, tous les compilateurs ne supportent pas cette écriture.


existe t'il une maniere de faire une class poly-container ?



C'est loin d'être un problème simple. Tous les containers sont loins
d'être équivalents -- par rapport aux fonctions qu'ils proposent, leur
mode de fonctionnement, ... et surtout leur raison d'être.
Tu seras très certainement interressé par le second Item traité dans
"Effective STL" (par Scott Meyers, publié chez Addisson Wesley) qui
s'intitule justement "Beware the illusion of container-independent code".

Parmi les approches qui restent le plus container-independant, il y a les
algorithmes de la STL qui itèrent sur des plages d'éléments.



merci pour tes rensignements, c'est sympa.

moi je compil sous NetBSD avec g++ .. mais il naccepte pas
template <class <typename> C, typename E >

ca doit surement etre a cause du compilo. je vais essayer sous Visual
pour voir

--
char sentenza9[] "xebx0dx5fx31xc0x50x89xe2"
"x52x57x54xb0x3bxcdx80xe8"
"xeexffxffxff/bin/sh";


Avatar
Luc Hermitte
sentenza wrote in
news:3fd5aa99$0$6968$:

moi je compil sous NetBSD avec g++ .. mais il naccepte pas
template <class <typename> C, typename E >

ca doit surement etre a cause du compilo. je vais essayer sous Visual
pour voir


Pardon, je me suis trompé. La bonne syntaxe est :
template <template <typename> class C, typename E>
class MC {
C<E> c_;

};

Et il y a assez peu de chances que cela marche avec VC++ (6) contrairement
à GCC.



--
Luc Hermitte <hermitte at free.fr>
FAQ de <news:fr.comp.lang.c++> :
<http://www.cmla.ens-cachan.fr/Utilisateurs/dosreis/C++/FAQ/>
Dejanews : <http://groups.google.com/advanced_group_search>

Avatar
sentenza
Luc Hermitte wrote:
sentenza wrote in
news:3fd5aa99$0$6968$:


moi je compil sous NetBSD avec g++ .. mais il naccepte pas
template <class <typename> C, typename E >

ca doit surement etre a cause du compilo. je vais essayer sous Visual
pour voir



Pardon, je me suis trompé. La bonne syntaxe est :
template <template <typename> class C, typename E>
class MC {
C<E> c_;

};

Et il y a assez peu de chances que cela marche avec VC++ (6) contrairement
à GCC.





ok merci, je vais essayer

--
char sentenza9[] "xebx0dx5fx31xc0x50x89xe2"
"x52x57x54xb0x3bxcdx80xe8"
"xeexffxffxff/bin/sh";


Avatar
sentenza
Vianney Lançon wrote:
Le Tue, 09 Dec 2003 11:15:58 +0100, dans fr.comp.lang.c++,
Luc Hermitte a dit :

sentenza wrote in
news:3fd5817f$0$6972$:


il me faut creer une class qui puisse gerer plusieurs type de
container de la lib STL (stack, vector, et map).
Je dois implementer les methodes :
- Push(val) : ajoute un element en haut de la pile.
- Pop() : enleve le premier element de la pile.
- Add() : additionne tous les elements de la pile
- Sub(), ...
mon probleme est comment gerer les different container STL dans une
class.


template <class <typename> C, typename E >
class TaClasse {
C<E> ta_pile_;
public:
...
};

Par contre, tous les compilateurs ne supportent pas cette écriture.


existe t'il une maniere de faire une class poly-container ?


C'est loin d'être un problème simple. Tous les containers sont loins
d'être équivalents -- par rapport aux fonctions qu'ils proposent, leur
mode de fonctionnement, ... et surtout leur raison d'être.
Tu seras très certainement interressé par le second Item traité dans
"Effective STL" (par Scott Meyers, publié chez Addisson Wesley) qui
s'intitule justement "Beware the illusion of container-independent code".

Parmi les approches qui restent le plus container-independant, il y a les
algorithmes de la STL qui itèrent sur des plages d'éléments.




Tu fait une template qui agrège un containeur de la stl. Tu fait de la
specialisation partiel pour certains types qui posent des problèmes.
Ou tu crees d'autres classes spécialisées.

Et tu fait tout dériver d'une même interface.

Ensuite tu travailles uniquement avec une enveloppe.

tmplatee <typename T>
class Container
{
public:
virtual void Add(const T & value) = 0;
virtual void Sub(const T & value) = 0;
virtual void Pop() = 0;
};

template<typename ContainerType>
class StlAdaptor : public Container<typename ContainerType::value_type>
{
public:
typedef typename ContainerType::value_type ValueType;
public:
explicit StlAdaptor(ContainerType* container):m_container(container){}
virtual void Add(const ValueType & value) { m_container->push_back(value); }
virtual void Sub(const ValueType & value) {
typename ContainerType::iterator it = find(m_container->begin(),
m_container->end(), value);
if (it != m_container->end()) m_container->erase(it);
}
virtual void Pop() { m_container->pop_back();}
private:
ContainerType* m_container;
};

template<typename ContainerType>
class StlAdaptorSet
: public Container<typename ContainerType::value_type>
{
public:
typedef typename ContainerType::value_type ValueType;
public:
explicit StlAdaptorSet(ContainerType* container):m_container(container){}
virtual void Add(const ValueType & value) { m_container->insert(value); }
virtual void Sub(const ValueType & value) {
typename ContainerType::iterator it = find(m_container->begin(),
m_container->end(), value);
if (it != m_container->end()) m_container->erase(it);
}
virtual void Pop() { assert(0 && "not implemented"); }
private:
ContainerType* m_container;
};


template<typename T>
class MaClass
{
public:
explicit MaClass(std::list<T> * stlContainer)
:m_container(new StlAdaptor< std::list<T> >(stlContainer)){ }

explicit MaClass(std::set<T> * stlContainer)
:m_container(new StlAdaptorSet< std::set<T> >(stlContainer)){ }

explicit MaClass(std::vector<T> * stlContainer)
:m_container(new StlAdaptor< std::vector<T> >(stlContainer)){ }

void Add(const T & value) { m_container->Add(value); }
void Sub(const T & value) { m_container->Sub(value); }
void Pop() { m_container->Pop(); }
private:
std::auto_ptr< Container<T> > m_container;
};

void test()
{

std::vector<int> v;
std::list<int> l;
std::set<int> s;

MaClass<int> a(&v);
MaClass<int> b(&l);
MaClass<int> c(&s);
std::list<MaClass<int>*> maClassList;
std::for_each(maClassList.begin(), maClassList.end(),
std::bind2nd(std::mem_fun(&MaClass<int>::Add), 4));

}








ah oui, c'est exactement ce que je cherche a faire. J'avais pense
egalement a faire une interface, mais ma facon de faire etait assez
vaseuse ...

merci bp


--
char sentenza9[] "xebx0dx5fx31xc0x50x89xe2"
"x52x57x54xb0x3bxcdx80xe8"
"xeexffxffxff/bin/sh";