Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Ajouter un typage fort

10 réponses
Avatar
ns2v
bonjour,

Je suis en train de chercher un moyen d'améliorer un mecanisme que
j'utilisais. Je bloque malheureusement sans trouver de solution. Si vous
pouviez me donner quelque indication sur comment je pourrais y arriver
(c'est peut etre un pattern deja existant, mais j'ai rien trouvé).

Voila le principe, les objects ont une liste de propriété qui peuvent etre
d'un certain nombre de type fixé à l'avance, accessible et modifiable de
manière générique. Concrètement, l'interface contient 2 methodes, un void *
GetField( int fieldId ); et un ECode SetField( int fieldId, void* val ); Le
problème principal que j'aimerais résoudre est celui d'ajouter un typage
fort sur ces méthodes, car cela eviterait les cast de et vers void*, pour
l'instant, je n'arrive à le resoudre qu'au prix d'une instance de ces
methodes (devenues template) pour chaque identifiant.

Le second problème vient de la création de classe avec des propriété, il
faut que cela soit un problème résolu uniquement a la compilation. Dans
l'ancienne version, il s'agissait d'un tableau static de struct du type {
int id, const char *name, void* pointeurSurMembre }. Il faudrait trouver un
moyen d'ameliorer la recherche de la propriété sans qu'il y est besoin d'un
travail supplémentaire au runtime car pour l'instant, SetField et GetField
sont obligé d'itéré dans leur tableau et ceux des classes de base.


Voila, j'èspère ne pas avoir été trop confus. Si quelqu'un aurait une idée,
merci.
Nicolas.

10 réponses

Avatar
Benoit Rousseau
ns2v wrote:
bonjour,

Je suis en train de chercher un moyen d'améliorer un mecanisme que
j'utilisais. Je bloque malheureusement sans trouver de solution. Si vous
pouviez me donner quelque indication sur comment je pourrais y arriver
(c'est peut etre un pattern deja existant, mais j'ai rien trouvé).

Voila le principe, les objects ont une liste de propriété qui peuvent etre
d'un certain nombre de type fixé à l'avance, accessible et modifiable de
manière générique. Concrètement, l'interface contient 2 methodes, un void *
GetField( int fieldId ); et un ECode SetField( int fieldId, void* val ); Le
problème principal que j'aimerais résoudre est celui d'ajouter un typage
fort sur ces méthodes, car cela eviterait les cast de et vers void*, pour
l'instant, je n'arrive à le resoudre qu'au prix d'une instance de ces
methodes (devenues template) pour chaque identifiant.

Le second problème vient de la création de classe avec des propriété, il
faut que cela soit un problème résolu uniquement a la compilation. Dans
l'ancienne version, il s'agissait d'un tableau static de struct du type {
int id, const char *name, void* pointeurSurMembre }. Il faudrait trouver un
moyen d'ameliorer la recherche de la propriété sans qu'il y est besoin d'un
travail supplémentaire au runtime car pour l'instant, SetField et GetField
sont obligé d'itéré dans leur tableau et ceux des classes de base.



Tu ne travaillerais pas sur un "compilateur" ? :-)
Je suis un peu confronté aux mêmes problèmes.
Pour le typage fort, j'ai fait comme toi, avec des templates, mais ca ne
me plait pas toujours.

Pour la résolution de noms, est ce que tu as pensé à "précompiler" ton
code ? Du bytecode et une machine virtuelle pourraient résoudre le
problème...

C'est peut-être l'artillerie lourde pour écraser une mouche, mais c'est
ce que j'ai trouvé de mieux à faire (et en plus ca me fait étudier les
machines virtuelles ;-)


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

Avatar
ns2v

Tu ne travaillerais pas sur un "compilateur" ? :-)


Pas du tout, c'est plus dans un but d'avoir des "controleurs" animés sur ces
propriétées, ainsi que de la sérialisation.

Je suis un peu confronté aux mêmes problèmes.
Pour le typage fort, j'ai fait comme toi, avec des templates, mais ca ne
me plait pas toujours.

Voui, mais je supose qu'il y a moyen de faire mieux, meme si cela va me

prendre 1 mois pour trouvé, comme il s'agit d'un élément de base, autant
qu'il soit béton.

C'est peut-être l'artillerie lourde pour écraser une mouche, mais c'est
ce que j'ai trouvé de mieux à faire (et en plus ca me fait étudier les
machines virtuelles ;-)

Pour le problème d'éfficacité, je pourrais pas exemple avoir un préprocess

sur le code qui repérererait des declaration de field et générerait les
définitions définitive trié pour un acces avec recherche dichotomique, mais
bon, a la rigueur, c'est de la sauce interne, ce qui me gène le plus, c'est
bien le typage sans ambiguité.

Avatar
Marc Boyer
ns2v wrote:
bonjour,

Je suis en train de chercher un moyen d'améliorer un mecanisme que
j'utilisais. Je bloque malheureusement sans trouver de solution. Si vous
pouviez me donner quelque indication sur comment je pourrais y arriver
(c'est peut etre un pattern deja existant, mais j'ai rien trouvé).


Je ne suis pas sur d'avoir vraiment compris le probleme,
alors ma solution est peut-être completement a cote de la plaque.

Voila le principe, les objects ont une liste de propriété qui peuvent etre
d'un certain nombre de type fixé à l'avance, accessible et modifiable de
manière générique. Concrètement, l'interface contient 2 methodes, un void *
GetField( int fieldId ); et un ECode SetField( int fieldId, void* val ); Le
problème principal que j'aimerais résoudre est celui d'ajouter un typage
fort sur ces méthodes, car cela eviterait les cast de et vers void*, pour
l'instant, je n'arrive à le resoudre qu'au prix d'une instance de ces
methodes (devenues template) pour chaque identifiant.


Tu peux pas préciser un peu, j'ai peur de te reproposer ta solution.

Le second problème vient de la création de classe avec des propriété, il
faut que cela soit un problème résolu uniquement a la compilation. Dans
l'ancienne version, il s'agissait d'un tableau static de struct du type {
int id, const char *name, void* pointeurSurMembre }. Il faudrait trouver un
moyen d'ameliorer la recherche de la propriété sans qu'il y est besoin d'un
travail supplémentaire au runtime car pour l'instant, SetField et GetField
sont obligé d'itéré dans leur tableau et ceux des classes de base.


Si je devine bien ton besoin, c'est impossible pour le moment, mais
Gabriel travaille sur une proposition d'évolution de C++ qui le rendrait
possible.

Marc Boyer
--
Lying for having sex or lying for making war? Trust US presidents :-(

Avatar
ns2v
Si je devine bien ton besoin, c'est impossible pour le moment, mais
Gabriel travaille sur une proposition d'évolution de C++ qui le rendrait
possible.

J'en suis arriver a cette conclusion aussi :( j'en suis obligé de séparer le

cas ou l'id est une constante de celui ou il est une variable, en bref,
c'est pas top.

Par contre, c qui ce gabriel ?

Avatar
Marc Boyer
In article <3fcb55ad$0$28616$, ns2v wrote:
Si je devine bien ton besoin, c'est impossible pour le moment, mais
Gabriel travaille sur une proposition d'évolution de C++ qui le rendrait
possible.

J'en suis arriver a cette conclusion aussi :( j'en suis obligé de séparer le

cas ou l'id est une constante de celui ou il est une variable, en bref,
c'est pas top.

Par contre, c qui ce gabriel ?


Gabriel Dos Reis, contributeur régulier de ce forum, mainteneur
d'une partie de GCC et membre du comité qui définit C++.
Une célébrité locale quoi ;-)

Ceci dit, c'est la partie "évitons le run-time" que je disais impossible.
La partie sur les GetField, j'ai besoin de plus de détail pour me faire une
idée (mais n'étant pas un as du C++, je promets pas d'avoir une idée
plus pertinente que ta solution actuelle).

Marc Boyer
--
Lying for having sex or lying for making war? Trust US presidents :-(


Avatar
Christophe Lephay
ns2v wrote:
Si je devine bien ton besoin, c'est impossible pour le moment,
mais Gabriel travaille sur une proposition d'évolution de C++ qui le
rendrait possible.
Par contre, c qui ce gabriel ?



La Bible, chapitre xx verset yy ;)

Chris


Avatar
Vianney Lançon
Le Mon, 1 Dec 2003 12:15:38 +0100, dans fr.comp.lang.c++,
ns2v a dit :
bonjour,

Je suis en train de chercher un moyen d'améliorer un mecanisme que
j'utilisais. Je bloque malheureusement sans trouver de solution. Si vous
pouviez me donner quelque indication sur comment je pourrais y arriver
(c'est peut etre un pattern deja existant, mais j'ai rien trouvé).

Voila le principe, les objects ont une liste de propriété qui peuvent etre
d'un certain nombre de type fixé à l'avance, accessible et modifiable de
manière générique. Concrètement, l'interface contient 2 methodes, un void *
GetField( int fieldId ); et un ECode SetField( int fieldId, void* val ); Le
problème principal que j'aimerais résoudre est celui d'ajouter un typage
fort sur ces méthodes, car cela eviterait les cast de et vers void*, pour
l'instant, je n'arrive à le resoudre qu'au prix d'une instance de ces
methodes (devenues template) pour chaque identifiant.

Le second problème vient de la création de classe avec des propriété, il
faut que cela soit un problème résolu uniquement a la compilation. Dans
l'ancienne version, il s'agissait d'un tableau static de struct du type {
int id, const char *name, void* pointeurSurMembre }. Il faudrait trouver un
moyen d'ameliorer la recherche de la propriété sans qu'il y est besoin d'un
travail supplémentaire au runtime car pour l'instant, SetField et GetField
sont obligé d'itéré dans leur tableau et ceux des classes de base.


Voila, j'èspère ne pas avoir été trop confus. Si quelqu'un aurait une idée,
merci.
Nicolas.




Une solution simple est d'utiliser une std::map<std::string, Property*>
avec Property définie par un couple de pointeur sur function membre
boost::any (T::*getPropperty)() const,
void (T::*setProperty)(const boost::any&).

En enrichissant boost::any tu peux avoir à la fois le un type-checking
fort et une souplesse d'execution.
Note importante *boost:any* n'est pas une classe templeté mais à un
constructeur templeté. Tu limite donc fortement le nombre d'instance de
classe templété.

En combinant un std::vector<Property*> une std::map<string, Property*>
et l'opertor typeid(), les type_traits de boost et la spécialisation de
template tu peux facilement créer une classe défini au runtime.


Si tu veux faire un maximum de travail à la compile-time tu à un certain
nombre d'outils : spécialisation de template,préprocesseur, m4, perl.

DEFINE_CLASS(Toto)
{
DEFINE_PROPERTY(int, x);
DEFINE_PROPERTY(float, y);
DEFINE_PROPERTY(double, z);
};

qui te génère

class Toto: public PropertyMap("Toto")
{
public:
static PropertyClass& createClassType()
{
return PropertyClassManager::getInstance().addClass("Toto")
.addProperty("X", &Toto::getAnyX, &Toto::setAnyX)

.addProperty("Y", &Toto::getAnyY, &Toto::setAnyY)

.addProperty("Z", &Toto::getAnyZ, &Toto::setAnyZ);

}

public:
int getX() const { return m_x; }
void setX(int x) { m_x = x; }}

float getY() const { return m_y; }
void setY(float y) { m_y = y; }

double getZ() const { return m_z; }
void setZ(double z) { m_z = z; }
protected:
boost::any getAnyX() const { return boost::any(getX());}
void setAnyX(boost::any x) { setX(boost::any_cast<int>(x)); }

boost::any getAnyY() const { returni boost::any(getY()) ;}
void setAnyY(boost::any y) { setX(boost::any_cast<float>(y));}

boost::any getAnyZ() const{ return boost::any(getZ());}
void setAnyZ(boost::any z) { setX( boost::any_cast<double>(Z));}

private:
int m_x;
float m_y;
double m_z;

};

et a l'utilisation Toto a;

a.set("X", 1);
a.set<float>("Y", 0.4);
a.set("Z", 4.3);

avec

template <typename T>
void PropertyMap::set(const std::string&, T value);


Tu peux regarder du côté de boost.Python pour des examples plus
complexes de fonctionnement. Mais tant que le c++ ne gère pas
l'introspection au niveau du langage, tu est plus ou moins limité
à te palucher ce genre de chose à la main.



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

Avatar
Laurent DELEPINE
ns2v wrote:
bonjour,

Je suis en train de chercher un moyen d'améliorer un mecanisme que
j'utilisais. Je bloque malheureusement sans trouver de solution. Si vous
pouviez me donner quelque indication sur comment je pourrais y arriver
(c'est peut etre un pattern deja existant, mais j'ai rien trouvé).

Voila le principe, les objects ont une liste de propriété qui peuvent etre
d'un certain nombre de type fixé à l'avance, accessible et modifiable de
manière générique. Concrètement, l'interface contient 2 methodes, un void *
GetField( int fieldId ); et un ECode SetField( int fieldId, void* val ); Le
problème principal que j'aimerais résoudre est celui d'ajouter un typage
fort sur ces méthodes, car cela eviterait les cast de et vers void*, pour
l'instant, je n'arrive à le resoudre qu'au prix d'une instance de ces
methodes (devenues template) pour chaque identifiant.


J'ai ecrit un programme similaire. J'avais resolu le probleme en
traduisant tout en texte : la valeur comme l'id de la propriété (en fait
le nom). Cela etait parfait pour moi puisque l'interface de
modification/consultation des propriétés était un interpreteur mode
texte (et que par ailleurs les classes etant definies dans des plugins,
l'usage du texte facilitait beaucoup la programmation). J'avais aussi
une fonction ShowFields qui permettait de connaitre la liste des
propriétés pour un objet donné.

Le second problème vient de la création de classe avec des propriété, il
faut que cela soit un problème résolu uniquement a la compilation. Dans
l'ancienne version, il s'agissait d'un tableau static de struct du type {
int id, const char *name, void* pointeurSurMembre }. Il faudrait trouver un
moyen d'ameliorer la recherche de la propriété sans qu'il y est besoin d'un
travail supplémentaire au runtime car pour l'instant, SetField et GetField
sont obligé d'itéré dans leur tableau et ceux des classes de base


Les classes contenaient leurs propriétés dans des membres normaux et
c'est les fonctions SetField et GetField (redefinie pour chaque classe)
qui se chargeaient de faire correspondre le nom d'une propriété au bon
argument. Il faut cependant préciser que certaones de mes propriétés
étaient trop complexes pour être rangées dans un tableau (par exemple
definition d'un graphique d'un nombre quelconque de point).

J'espère avoir bien compris ce que tu voulais.


A+

LD

Avatar
kanze
"ns2v" wrote in message
news:<3fcb230b$0$28639$...

Je suis en train de chercher un moyen d'améliorer un mecanisme que
j'utilisais. Je bloque malheureusement sans trouver de solution. Si
vous pouviez me donner quelque indication sur comment je pourrais y
arriver (c'est peut etre un pattern deja existant, mais j'ai rien
trouvé).

Voila le principe, les objects ont une liste de propriété qui peuvent
etre d'un certain nombre de type fixé à l'avance, accessible et
modifiable de manière générique. Concrètement, l'interface contient 2
methodes, un void * GetField( int fieldId ); et un ECode SetField( int
fieldId, void* val ); Le problème principal que j'aimerais résoudre
est celui d'ajouter un typage fort sur ces méthodes, car cela
eviterait les cast de et vers void*, pour l'instant, je n'arrive à le
resoudre qu'au prix d'une instance de ces methodes (devenues template)
pour chaque identifiant.


Il n'y aurait pas comme une contradiction là dedans. Supposons que le
champs 1 est un double et le champs 2 un std::string. Quel doit être le
type de rétour de getField ?

Le mieux que tu pourrais faire, c'est d'encapsuler tous les types dans
une classe, de façon à pouvoir faire une vérification de type lors de
l'execution. Je crois que boost::any ferait l'affaire, mais sinon,
quelque chose du genre :

struct AbstractContainer
{
virtual ~AbstractContainer() {}
} ;

template< typename T >
class Container : public virtual AbstractContainer
{
public:
Container( T const& initialValue = T() ) : myValue( initialValue ) {}
T const& get() const { return myValue ; }
void set( T const& newValue ) { myValue = newValue ; }
private:
T myValue ;
} ;

Ton getField renvoie alors un AbstractContainer const*, et il faut un
dynamic_cast (avec vérification dynamic du type) pour arriver à la
valeur.

Mais comme j'ai dit, Boost l'a complètement implémenté, avec sans doute
des trucs en plus.

Le second problème vient de la création de classe avec des propriété,
il faut que cela soit un problème résolu uniquement a la compilation.
Dans l'ancienne version, il s'agissait d'un tableau static de struct
du type { int id, const char *name, void* pointeurSurMembre }. Il
faudrait trouver un moyen d'ameliorer la recherche de la propriété
sans qu'il y est besoin d'un travail supplémentaire au runtime car
pour l'instant, SetField et GetField sont obligé d'itéré dans leur
tableau et ceux des classes de base.


Dans la mesure que tu veux choisir une attribute selon une clé
dynamique, je ne vois pas comment il pourrait être autrement. Sinon, tu
peux toujours appeler getField1, getField2, etc., sans problème.

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

Avatar
kanze
"Christophe Lephay" wrote in message
news:<bqfm5g$51p$...
ns2v wrote:
Si je devine bien ton besoin, c'est impossible pour le moment,
mais Gabriel travaille sur une proposition d'évolution de C++ qui
le rendrait possible.


Par contre, c qui ce gabriel ?


La Bible, chapitre xx verset yy ;)


C'est le messager du Dieu, depuis qu'il travaille à côté de Dieu ? (Mais
j'ai toujours eu un côté héritique. C'est peut-être pour ça qu'on se
dispute si souvent:-).)

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16