OVH Cloud OVH Cloud

Question de conception via les templates.

34 réponses
Avatar
Stephane Wirtel
Bonjour,

Voici un bout de code que je suis entrain de pondre afin de créer une
lecture de settings et initialisation de ces fameux settings de manière
automatique.

#include <iostream>
#include <string>
#include <list>

using namespace std;

template <class T> class ItemSetting {
public:
ItemSetting (void) {
// cout << "ItemSetting::ItemSetting" << endl;
}
~ItemSetting (void) {
// cout << "ItemSetting::~ItemSetting" << endl;
}
};

class Settings {
public:
Settings (void) {
cout << "Settings::Settings" << endl;
}
~Settings (void) {
cout << "Settings::~Settings" << endl;
}
private:
ItemSetting <bool> boolItemSetting;
ItemSetting <int> intItemSetting;
ItemSetting <char> charItemSetting;
ItemSetting <double> doubleItemSetting;
};

int main (int argc, char **argv) {
cout << "Size of Setting : " << sizeof (Settings) << endl;
return 0;
}

Dans mon main, ou via le constructeur de Settings, j'aimerais savoir si il
est possible de faire une boucle sur tous les variables "ItemSetting <XXX>"
se trouvant dans la partie "private" et d'initialiser toutes les variables.

Je me dis que j'aurais pû créer un std::vector de tous les ItemSettings et
via un std::iterator les initialiser via une boucle. Le problème est que
l'on ne peut pas mettre un type template dans un container de la STL.

Est-ce que quelqu'un aurait déjà songé à ce style de programmation ?

Merci,

PS : Il ne s'agit que d'un essai, pour voir les possibilités de la
Meta-programmation.

--
Stephane Wirtel <stephane.wirtel@belgacom.net>

10 réponses

1 2 3 4
Avatar
Fabien LE LEZ
On Sat, 07 May 2005 20:02:33 +0200, Stephane Wirtel
:

Le problème est que
l'on ne peut pas mettre un type template dans un container de la STL.


Va voir chez Boost, il ont peut-être ce qu'il te faut.
--
Le grand site de la philosophie animale : <http://perso.edulang.com/philo/>

Avatar
Stephane Wirtel
Fabien LE LEZ wrote:

On Sat, 07 May 2005 20:02:33 +0200, Stephane Wirtel
:

Le problème est que
l'on ne peut pas mettre un type template dans un container de la STL.


Va voir chez Boost, il ont peut-être ce qu'il te faut.


Salut Fabien,

Je ne pense pas que je puisse simuler une liste d'instance d'objet utilisant
des templates de manière statique.

Qu'est-ce que tu en penses ?

--
Stephane Wirtel


Avatar
Fabien LE LEZ
On Sat, 07 May 2005 22:44:17 +0200, Stephane Wirtel
:

Je ne pense pas que je puisse simuler une liste d'instance d'objet utilisant
des templates de manière statique.


Comme ça, brut de fonderie, non. Mais je crois avoir vu quelque chose
d'approchant chez Boost. Je ne m'en souviens pas plus que ça, mais
bon, boost:: n'est pas si gros que ça, ça ne devrait pas être trop dur
à retrouver...

--
Le grand site de la philosophie animale : <http://perso.edulang.com/philo/>

Avatar
Stephane Wirtel
Fabien LE LEZ wrote:

On Sat, 07 May 2005 22:44:17 +0200, Stephane Wirtel
:

Je ne pense pas que je puisse simuler une liste d'instance d'objet
utilisant des templates de manière statique.


Comme ça, brut de fonderie, non. Mais je crois avoir vu quelque chose
d'approchant chez Boost. Je ne m'en souviens pas plus que ça, mais
bon, boost:: n'est pas si gros que ça, ça ne devrait pas être trop dur
à retrouver...

J'espère trouver ;-)


Merci,

Allons joyeusement regarder Boost :-)
--
Stephane Wirtel


Avatar
Patrick 'Zener' Brunet
Bonjour.

Bonjour,

Voici un bout de code que je suis entrain de pondre afin de créer une
lecture de settings et initialisation de ces fameux settings de
manière automatique.

#include <iostream>
#include <string>
#include <list>

using namespace std;

template <class T> class ItemSetting {
public:
ItemSetting (void) {
// cout << "ItemSetting::ItemSetting" << endl;
}
~ItemSetting (void) {
// cout << "ItemSetting::~ItemSetting" << endl;
}
};

class Settings {
public:
Settings (void) {
cout << "Settings::Settings" << endl;
}
~Settings (void) {
cout << "Settings::~Settings" << endl;
}
private:
ItemSetting <bool> boolItemSetting;
ItemSetting <int> intItemSetting;
ItemSetting <char> charItemSetting;
ItemSetting <double> doubleItemSetting;
};

int main (int argc, char **argv) {
cout << "Size of Setting : " << sizeof (Settings) << endl;
return 0;
}

Dans mon main, ou via le constructeur de Settings, j'aimerais savoir
si il est possible de faire une boucle sur tous les variables
"ItemSetting <XXX>" se trouvant dans la partie "private" et
d'initialiser toutes les variables.
[...]

Est-ce que quelqu'un aurait déjà songé à ce style de programmation ?



Oh que oui :-D !

Il y a une technique (dont j'ai pipé l'idée de base dans les factories de
COM-à-l'ancienne) et que j'ai pu utiliser avec succès : elle permet de
constituer une daisy-chain avec les objets en question au moment de leur
construction.

Bien sûr, une daisy-chain c'est pas top pratique, mais ça suffit largement
pour atteindre le but.

L'idée est de déclarer un pointeur initialisé à NULL - ou valeur équivalente
pour les gens pointilleux ;-) - dans le container (et s'il n'y en avait pas
ce serait une globale). Et ensuite de passer ***l'adresse de*** ce pointeur
(ou une référence) en argument de construction à tous les objets à lister.

L'astuce est que (du moins dans un contexte non parallèle !!!), le pointeur
est initialisé en premier, et ensuite les objets sont construits un par un
(on a une petite idée de l'ordre dans votre contexte, mais en fait on s'en
fiche).

Il suffit alors que le constructeur de l'objet, recevant un tel pointeur
passé par adresse, fasse la transformation consistant à enfiler l'objet
courant en tête de liste (optimal), l'objet contenant donc un pointeur
"next".

Lorsque tous les objets sont construits, ils sont tous enfilés sur cette
daisy-chain, et donc il suffit de la parcourir pour exécuter itérativement
toute forme de tâche de "prise de contact" plus sophistiquée avec le
container...

PS : Il ne s'agit que d'un essai, pour voir les possibilités de la
Meta-programmation.


La méta-programmation, c'est l'avenir et c'est toute ma vie ... Et vous vous
en faites quoi ?

Cordialement,

--
/***************************************
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
***************************************/

Avatar
Stephane Wirtel
Est-ce que quelqu'un aurait déjà songé à ce style de programmation ?



Oh que oui :-D !

Il y a une technique (dont j'ai pipé l'idée de base dans les factories de
COM-à-l'ancienne) et que j'ai pu utiliser avec succès : elle permet de
constituer une daisy-chain avec les objets en question au moment de leur
construction.

Bien sûr, une daisy-chain c'est pas top pratique, mais ça suffit largement
pour atteindre le but.
Qu'est-ce qu'une daisy-chain ?



L'idée est de déclarer un pointeur initialisé à NULL - ou valeur
équivalente pour les gens pointilleux ;-) - dans le container (et s'il n'y
en avait pas ce serait une globale). Et ensuite de passer ***l'adresse
de*** ce pointeur (ou une référence) en argument de construction à tous
les objets à lister.

L'astuce est que (du moins dans un contexte non parallèle !!!), le
pointeur est initialisé en premier, et ensuite les objets sont construits
un par un (on a une petite idée de l'ordre dans votre contexte, mais en
fait on s'en fiche).

Il suffit alors que le constructeur de l'objet, recevant un tel pointeur
passé par adresse, fasse la transformation consistant à enfiler l'objet
courant en tête de liste (optimal), l'objet contenant donc un pointeur
"next".

Lorsque tous les objets sont construits, ils sont tous enfilés sur cette
daisy-chain, et donc il suffit de la parcourir pour exécuter itérativement
toute forme de tâche de "prise de contact" plus sophistiquée avec le
container...
J'ai bien l'impression que cette technique va m'aider à réaliser ma classe

Settings. Par après, je pourrai la spécialiser ou simplement créer une ou
plusieurs classes pour spécifier le type de support ou se trouvent les
infos (GConf, Fichier INI, Fichier XML, Base de registre Windows, ou
pourquoi pas "Base de données").


PS : Il ne s'agit que d'un essai, pour voir les possibilités de la
Meta-programmation.


La méta-programmation, c'est l'avenir et c'est toute ma vie ... Et vous
vous en faites quoi ?
J'essaie d'apprendre et de voir les possibilités de cette technique forte

intéressante.

En parlant de possibilités, pourriez-vous me montrer un extrait de ce qu'il
est possible de faire via la méta-programmation ?

En outre, j'ai acheté afin d'apprendre correctement, deux ouvrages qui
semblent être de références. Le premier étant C++ Template, et le second
C++ Template Metaprogramming. Qu'en pensez-vous ?



Cordialement,
Cordialement,


--
/***************************************
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
***************************************/


--
Stephane Wirtel


Avatar
Arnaud Debaene
Stephane Wirtel wrote:
Bonjour,

Voici un bout de code que je suis entrain de pondre afin de créer une
lecture de settings et initialisation de ces fameux settings de
manière automatique.

#include <iostream>
#include <string>
#include <list>

using namespace std;

template <class T> class ItemSetting {
public:
ItemSetting (void) {
// cout << "ItemSetting::ItemSetting" << endl;
}
~ItemSetting (void) {
// cout << "ItemSetting::~ItemSetting" << endl;
}
};

class Settings {
public:
Settings (void) {
cout << "Settings::Settings" << endl;
}
~Settings (void) {
cout << "Settings::~Settings" << endl;
}
private:
ItemSetting <bool> boolItemSetting;
ItemSetting <int> intItemSetting;
ItemSetting <char> charItemSetting;
ItemSetting <double> doubleItemSetting;
};

int main (int argc, char **argv) {
cout << "Size of Setting : " << sizeof (Settings) << endl;
return 0;
}

Dans mon main, ou via le constructeur de Settings, j'aimerais savoir
si il est possible de faire une boucle sur tous les variables
"ItemSetting <XXX>" se trouvant dans la partie "private" et
d'initialiser toutes les variables.

Je me dis que j'aurais pû créer un std::vector de tous les
ItemSettings et via un std::iterator les initialiser via une boucle.
Le problème est que l'on ne peut pas mettre un type template dans un
container de la STL.
En méta-programmation template, tout se fait à la compilation, alors que les

conteneurs de la STL fonctionnent au run-time.
C'est difficile de te conseiller sans savoir ce que tu veux faire
exactement, mais peut-être que les typelists pourraient t'intéresser :
Regardes du côté de la librairie Loki.

Arnaud

Avatar
Stephane Wirtel
Suite de ma classe Settings.

à l'aide de Fabien LE LEZ, j'ai vu dans la lib Boost, qu'il y avait
boost::any, voici un petit code que j'ai réalisé, mais qui ne fait pas
encore tout ce que j'aimerais.

#include <map>
#include <boost/any.hpp>
#include <string>
#include <iostream>

typedef std::map <std::string, boost::any> MapProperties;

int main (int argc, char **argv) {
MapProperties mapProperties;
mapProperties ["OperatingSystem"] = std::string ("Linux");
mapProperties ["Port"] = 25;
mapProperties ["IsActive"] = false;

for (MapProperties::const_iterator It = mapProperties.begin ();
It != mapProperties.end ();
++It) {
// int port = boost::any_cast <int> (mapProperties ["Port"]);
// std::cout << "Port : " << port << std::endl;
std::cout << "Nom : " << It->first << std::endl;
// std::cout << It->second.type().name() << std::endl;
}
return 0;
}

Donc, le but de ce code, est d'essayer de m'afficher.
Nom : OperatingSystem
Value : Linux

Nom : Port
Value : 25

Nom : IsActive
Value : 0


Le problème est que l'objet boost::any ne me permet pas de récupérer
directement la valeur sous le type de variable dans laquelle cette dite
valeur a été insérée dans l'objet boost::any.

Afin de corriger cela, il est possible de faire un cast, via boost::any_cast

Donc, par exemple pour liste la valeur pour la variable "Port", je suis
obligé de faire :
int port = boost::any_cast <int> (mapProperties ["Port"]);

Mais je ne peux pas me permettre de faire cela, si je veux afficher la liste
des propriétés, ainsi que leur valeur.

Quelqu'un aurait-il une idée ?

Je cherche toujours,

Merci
Avatar
Stephane Wirtel
En méta-programmation template, tout se fait à la compilation, alors que
les conteneurs de la STL fonctionnent au run-time.
C'est difficile de te conseiller sans savoir ce que tu veux faire
exactement, mais peut-être que les typelists pourraient t'intéresser :
Regardes du côté de la librairie Loki.
Pourrais-tu me parler des typelists ?


Stéphane

Arnaud


--
Stephane Wirtel

Avatar
Patrick 'Zener' Brunet
Bonjour.

Suite de ma classe Settings.
[...] (le code)
Donc, par exemple pour liste la valeur pour la variable "Port", je
suis obligé de faire :
int port = boost::any_cast <int> (mapProperties ["Port"]);

Mais je ne peux pas me permettre de faire cela, si je veux afficher
la liste des propriétés, ainsi que leur valeur.

Quelqu'un aurait-il une idée ?

Je cherche toujours,



Ca m'a tout l'air d'être du retypage dynamique que vous voulez faire !
Dans cette hypothèse :

C'est pas possible ***a priori*** en C++ parce que ça signifie faire du
typage au runtime alors que c'est le boulot du compilateur.

Mais il est envisageable de le faire "à moitié", c'est à dire d'écrire une
classe template qui a l'air de le faire au runtime mais qui en fait le fait
au compiletime. Donc du point de vue de l'utilisateur de cette classe, c'est
équivalent.

En fait, sauf dans le contexte de l'IA, le code est toujours 100% typé au
compiletime, et donc ce qu'on veut, c'est en somme "oublier" le type dans le
chargement de la classe, et laisser le compilo le "redeviner" ailleurs.

C'est un peu ce que fait la classe suivante : il s'agit d'un container de
type "jointure", capable de stocker des pointeurs hétérogènes. Je ne le
standardise pas, mais cette partie de mes standards est assez facile à
comprendre : Uint est un entier non signé, les tags _in_, _out_ sont des
macros sémantiques, évaluant à vide.

Ce qu'il faut comprendre dans ce code, c'est que chaque pointeur de la liste
est identifié par son rôle, qui est construit par la macro fournie, et qui
définit ***à la fois un type et un indice*** de rangement dans la jointure.
Toute l'astuce est là.

Bien sûr ce code va faire hûûûûûrler :-@ tous les puristes, mais il a le
mérite de réaliser ce truc théoriquement impossible :-P. Donc je vous le
passe "as is".

template< Uint C>
class CmJointureP;

template< class T>
class CmJointurePSlot
{
private:
T * _pxTarget;
public:
inline
CmJointurePSlot( _in_ T * const pkxTarget)
{
_pxTarget = pkxTarget;
};
public:
inline
operator T * ( void) const
{
return( _pxTarget);
};
inline T *
operator -> ( void) const
{
return( _pxTarget);
};
};

template< Uint C>
class CmJointureP
{
private:
void * _capvRoom[C];
public:
inline
CmJointureP( void)
{
memset( _capvRoom, 0x00, sizeof( _capvRoom));
};
public:
template< class T>
inline void
SetAt( _in_ T * pxiRole,
_in_ T * pxTarget)
{
EZ_ASSERTKILL( (Uint) pxiRole < C) // Ca c'est équivalent à un
assert classique
new( &_capvRoom[(Uint) pxiRole]) CmJointurePSlot< T>( pxTarget);
};
template< class T>
inline T *
operator [] ( _in_ T * pxiRole)
{
return( (T *) *((CmJointurePSlot< T> *) (&_capvRoom[(Uint)
pxiRole])));
};
};

/****************************************
* Associated macros :
****************************************/

#define CmJointureP_MATCH( _nRole, _uValue, _nType)
static _nType * const _nRole = (_nType *) _uValue;
/* End of Macro */

Note additionnelle : la présence d'un "operator -> " dans un template
déclenche un warning de sécurité, c'est normal mais ici l'opérateur est
légitime, il y a aussi un pragma pour faire taire ce warning en principe.

///Je m'aperçois également que nous n'avons pas la même définition du mot
"méta-programmation". En fait je mets en oeuvre des techniques de
méta-conception (assistée par des techniques IA) dans lesquelles il y a
plusieurs niveaux de recul par rapport au codage, aussi sophistiqué
soit-il... Mais bon ça c'est ma cuisine...///

Si cette astuce technique vous intéresse, tenez-nous au courant...

Cordialement,

--
/***************************************
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
***************************************/

1 2 3 4