OVH Cloud OVH Cloud

conversion de vector en vector

10 réponses
Avatar
adebaene
Bonjour,

Je me retrouve confront=E9 =E0 un petit probl=E8me de conception : J'ai
une classe "Waitable" dont h=E9rite plusieurs types "Mutex",
"Semaphore", "MaPrimitiveBloquanteAMoi", etc...

Waitable a une m=E9thode statique WaitMultiple. Au d=E9part, je pensais
=E9crire:
ReturnType Waitable::WaitMultiple(vector<Waitable*> objects, bool
WaitAll, unsigned timeout);

Le probl=E8me est qu'=E0 l'utilisation, j'ai le plus souvent un
vector<Mutex*> ou bien un vector<Semaphore*>, etc... Hors
vector<Derived*> n'est pas convertible en vector<Base*> : je comprends
bien le pourquoi de cette limitation, mais comment =E9crire
WaitMultiple?

La seule solution qui m'est venu =E0 l'esprit, c'est de passer un
tableau "=E0 la C" =E0 WaitMultiple (avec sa taille), et ca ne me plait
pas. Y'a-t-il d'autres alternatives?

Merci d'avance.

Arnaud

10 réponses

Avatar
Aurélien REGAT-BARREL
Bonjour,

Tu peux créer WaitMultiple comme étant une fonction membre template qui
accepte un vector de T, T étant considéré comme un Base*.

--
Aurélien REGAT-BARREL

wrote:
Bonjour,

Je me retrouve confronté à un petit problème de conception : J'ai
une classe "Waitable" dont hérite plusieurs types "Mutex",
"Semaphore", "MaPrimitiveBloquanteAMoi", etc...

Waitable a une méthode statique WaitMultiple. Au départ, je pensais
écrire:
ReturnType Waitable::WaitMultiple(vector<Waitable*> objects, bool
WaitAll, unsigned timeout);

Le problème est qu'à l'utilisation, j'ai le plus souvent un
vector<Mutex*> ou bien un vector<Semaphore*>, etc... Hors
vector<Derived*> n'est pas convertible en vector<Base*> : je comprends
bien le pourquoi de cette limitation, mais comment écrire
WaitMultiple?

La seule solution qui m'est venu à l'esprit, c'est de passer un
tableau "à la C" à WaitMultiple (avec sa taille), et ca ne me plait
pas. Y'a-t-il d'autres alternatives?

Merci d'avance.

Arnaud


Avatar
Christophe de VIENNE
Bonjour,

Je me retrouve confronté à un petit problème de conception : J'ai
une classe "Waitable" dont hérite plusieurs types "Mutex",
"Semaphore", "MaPrimitiveBloquanteAMoi", etc...

Waitable a une méthode statique WaitMultiple. Au départ, je pensais
écrire:
ReturnType Waitable::WaitMultiple(vector<Waitable*> objects, bool
WaitAll, unsigned timeout);

Le problème est qu'à l'utilisation, j'ai le plus souvent un
vector<Mutex*> ou bien un vector<Semaphore*>, etc... Hors
vector<Derived*> n'est pas convertible en vector<Base*> : je comprends
bien le pourquoi de cette limitation, mais comment écrire
WaitMultiple?


Une possibilité est d'utiliser les templates :

! class Waitable {
! template<InputIterator>
! static ReturnType WaitMultiple(InputIterator first,
InputIterator last, bool WaitAll, unsigned timeout);
! }

Comme ça tu peux donner en paramètre n'importe quel conteneur (ses
iterateurs de début et de fin pour être exact) contenant des objets
dérivant de Waitable.

A+

Christophe

--
Christophe de Vienne

Avatar
korchkidu
wrote:

Bonjour,

Le problème est qu'à l'utilisation, j'ai le plus souvent un
vector<Mutex*> ou bien un vector<Semaphore*>, etc... Hors
vector<Derived*> n'est pas convertible en vector<Base*> : je comprends
bien le pourquoi de cette limitation, mais comment écrire
WaitMultiple?
Ben moi je comprends pas vraiment le pourquoi de cette limitation en fait...

Qq1 peut detailler SVP?

K.

Avatar
kanze
korchkidu wrote:
wrote:

Le problème est qu'à l'utilisation, j'ai le plus souvent un
vector<Mutex*> ou bien un vector<Semaphore*>, etc... Hors
vector<Derived*> n'est pas convertible en vector<Base*> : je
comprends bien le pourquoi de cette limitation, mais comment
écrire WaitMultiple?


Ben moi je comprends pas vraiment le pourquoi de cette
limitation en fait... Qq1 peut detailler SVP?


Sans doute parce qu'on l'estimait inutile, étant donné le temps
d'exécution qu'il exigerait. Une conversion implique la création
d'un nouveau object.

Si tu le veux vraiment, et que tu as un object vector<Derived*>,
tu peux bien faire:

std::vector< Base* >( derivedV.begin(), derivedV.end() )

Ça fait exactement ce que ferait le cast, s'il était légal.

--
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


Avatar
adebaene
korchkidu wrote:
wrote:

Bonjour,

Le problème est qu'à l'utilisation, j'ai le plus souvent un
vector<Mutex*> ou bien un vector<Semaphore*>, etc... Hors
vector<Derived*> n'est pas convertible en vector<Base*> : je
comprends


bien le pourquoi de cette limitation, mais comment écrire
WaitMultiple?
Ben moi je comprends pas vraiment le pourquoi de cette limitation en

fait...

Qq1 peut detailler SVP?


Voilà ce qu'on pourrait faire si la conversion était autorisée :

void function(vector<Base*>& tableau)
{
tableau.push_back(new AutreClasseDerivee); //localement, code
valide
}

vector<Derived*> t;
t.push_back(new Derived);
//ok : t ne contient que des Derived*

function(t);
//oups! le contenu de t est hétérogène!!!

En fait, il faudrait permettre uniquement la conversion
vector<Derived*> --> const vector<Base*>, mais je ne pense pas que le
langage le permette.

Arnaud


Avatar
korchkidu
wrote:

Voilà ce qu'on pourrait faire si la conversion était autorisée :

void function(vector<Base*>& tableau)
{
tableau.push_back(new AutreClasseDerivee); //localement, code
valide
}

vector<Derived*> t;
t.push_back(new Derived);
//ok : t ne contient que des Derived*

function(t);
//oups! le contenu de t est hétérogène!!!
Ah oui, d'accord. Merci pour l'eclaircissement.


K.

Avatar
Michel Michaud
Dans le message ,
korchkidu wrote:
wrote:
vector<Derived*> n'est pas convertible en vector<Base*> : je
Ben moi je comprends pas vraiment le pourquoi de cette limitation

en fait... Qq1 peut detailler SVP?


Voilà ce qu'on pourrait faire si la conversion était autorisée :
[...]


En fait, pour la même raison,

void F(Base*&);

n'accepte pas non plus

Derivé* p;
F(p);

Comme quoi, on ne peut pas utiliser un pointeur sur une classe
dérivée partout où l'on peut utiliser un pointeur sur la classe
de base... :-)

--
Michel Michaud
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/



Avatar
Fabien LE LEZ
On Wed, 23 Feb 2005 10:04:34 -0500, "Michel Michaud" :

Comme quoi, on ne peut pas utiliser un pointeur sur une classe
dérivée partout où l'on peut utiliser un pointeur sur la classe
de base... :-)


C'est exact, et j'espère que personne n'a dit le contraire.


--
;-)

Avatar
Arnaud Debaene
Christophe de VIENNE wrote:


Une possibilité est d'utiliser les templates :

! class Waitable {
! template<InputIterator>
! static ReturnType WaitMultiple(InputIterator first,
InputIterator last, bool WaitAll, unsigned timeout);
! }

Comme ça tu peux donner en paramètre n'importe quel conteneur (ses
iterateurs de début et de fin pour être exact) contenant des objets
dérivant de Waitable.


Merci à Christophe et Aurélien pour leurs idées. Je n'ai pas encore le
réflexe"template" pour ce genre de problèmes :-)

Arnaud

Avatar
kanze
Michel Michaud wrote:
Dans le message
,
a

korchkidu wrote:
wrote:
vector<Derived*> n'est pas convertible en vector<Base*> :
je
Ben moi je comprends pas vraiment le pourquoi de cette

limitation en fait... Qq1 peut detailler SVP?


Voilà ce qu'on pourrait faire si la conversion était
autorisée :
[...]


En fait, pour la même raison,

void F(Base*&);

n'accepte pas non plus

Derivé* p;
F(p);


Je ne vois pas le rapport. Dans ton exemple, il s'agit d'une
conversion de référence, dont le résultat est un lvalue, qui
doit permettre l'accès direct à l'objet initial. Dans le cas en
question, il s'agit de convertir un objet de type
vector<Derived*> en objet de type vector<Base*>. En principe, on
pourrait très bien le supporter -- on peut en fait avoir
exactement le même résultat déjà avec une syntaxe légèrement
différente :

std::vector<Base*>( derived.begin(), derived.end() ) ;

(Ce n'est pas tout à fait pareil, parce que ici, il me faut deux
références à derived. Donc, un objet que je peux nommer, et non
un temporaire.)

Il serait assez trivial, même aujourd'hui, d'ajouter une
fonction membre :

template< typename C >
std::vector<T>::operator C()
{
return C( begin(), end() ) ;
}

et son équivalent const. Seulement, j'imagine que très peu de
gens aimeraient qu'une telle conversion soit implicite. Avec
quelque chose comme boost::enable_if ou des contraints, on
pourrait ajouter un constructeur :

template< typename C >
std::vector<T>::vector( C const& other )
{
// Contraint : C a des fonctions membre begin() et end()
// initialiser avec other.begin() et other.end() ...
}

Constructeur qu'on ferait explicit, évidemment.

Mais est-ce qu'on veut réelement de telles conversions, vue
leur prix en temps d'exécution. Je ne suis pas exactement ce
qu'on pourrait qualifier de maniaque de performance, mais il y a
des limites même pour moi. (Encore qu'explicit...)

Comme quoi, on ne peut pas utiliser un pointeur sur une classe
dérivée partout où l'on peut utiliser un pointeur sur la
classe de base... :-)


Dit comme ça... Mais la règle, c'est qu'on peut se servir d'un
objet de type dérivé partout où on peut se servir d'un objet de
type base. C'est clair qu'il n'y a aucun rapport d'héritage
entre les pointeurs mêmes, quand on les considère comme des
objets.

--
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