OVH Cloud OVH Cloud

Utilisation de spécialisation de template pour convertir.

33 réponses
Avatar
Stephane Wirtel
Bonjour,

Est-il possible de créer un template via spécialisation permettant
de convertir des types définit (bool, int, string, ...) vers un
std::string ?

Je m'explique.

J'essaie de créer une classe permettant de lire des settings provenant d'un
fichier de conf.

Donc, dedans, j'ai créé une méthode générique, du style :

class Settings {
private:
typedef std::map <std::string, std::string> MapSettings;
MapSettings mSettings;
public:
template <class T> const T& Read (const std::string& pVariable,
const T& pDefaultValue) {
/**
* Si variable présente dans la map on retourne la valeur
* trouvée, sinon, on retourne la valeur par défaut.
* On rajoute tout de même pDefaultValue dans map pour une prochaine
* utilisation.
*/

mSettings[pVariable] = TranslateToString (pDefaultValue);

return pDefaultValue;
}
};

Ce que j'aimerais c'est que TranslateToString prenne ma valeur et la
transforme directement en chaine de caractère.
Pour cela, j'avais pensé à un template sur une fonction ou sur une méthode,
mais cela ne semble pas fonctionner correctement. Voir mon post précédent.

Mais sinon, j'avais pensé à ceci.

dans ma classe Settings, il y aurait la méthode TranslateToString définie
comme suit :
class Settings {
private:
...
public:
...
template <class T> std::string TranslateToString (const T& pValue) {
}
template <> std::string TranslateToString <bool> (const bool& pValue) {
return (pValue ? "True" : "False");
}
template <> std::string TranslateToString <int> (const int& pValue) {
return "Chaine de test...";
}
};

Est-ce que quelqu'un peut m'aider ? Il me manque une solution pour résoudre
mon problème qui je pense doit certainement avec une réponse de ce type.

Merci d'avance,


Stéphane
--
Stephane Wirtel <stephane.wirtel@belgacom.net>

10 réponses

1 2 3 4
Avatar
Stephane Wirtel
wrote:

Pierre THIERRY wrote:
simplement que je veux intégrer dans une map des types
différents reconvertit en std::string.


Et tu voit une autre utilité à un opérateur de cast et un
constructeur de conversion que reconvertir ??


Sauf qu'on ne veut pas que les conversions se font n'importe où,
sans qu'on se rende compte. Ce qu'il lui faut, ce sont des
conversions explicites.

Aussi, en passant, les types dans son exemple était bool et int.
Comment fais-tu à leur donner une conversion implicite de et en
std::string ?

À sa place, je jetterais un coup d'oeil du côté boost::any ou
boost::lexical_cast.
Je suis actuellement entrain de regarder à boost::any, car c'est Fabien LE

LEZ qui en a parlé lors d'un de mes précédents posts.

La raison pour laquelle je voulais convertir tous les types de bases vers un
std::string, est que cela me permettait de créer une std::map contenant mes
préférences et ensuite sauver dans un fichier text au format INI ou XML. Ou
voir même dans une base de données.



ou alors j'ai rien compris aux templates.


Ça n'a pas le moindre début de commencement de rapport avec
les templates, les conversions. Elles se font par le biais de
de méthodes parfaitement spécifiques, dans les classes.
Tu arrives à surcharger le type bool ou int au point tel qu'il t'est


possible de créer une méthode de transtypage avec les operator bool (),
int (), etc... ?


Pas forcement. Elles se font surtout par des opérateurs de
conversion, du genre static_cast ou dynamic_cast. Ou des
templates conçus sur le même modèle, comme boost::lexical_cast.
Je vais aller regarder du côté de boost::lexical_cast dès ce soir.


Quant aux fonctions spécifiques... il faut bien qu'elles aient
un nom standardisé, si on veut s'en servir dans un template. Et
qu'il ne soit pas une fonction membre, parce que sinon, il faut
traiter des types de base différemment des types de classe.


Merci James,

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


--
Stephane Wirtel



Avatar
kanze
Stephane Wirtel wrote:
wrote:

Pierre THIERRY wrote:
simplement que je veux intégrer dans une map des types
différents reconvertit en std::string.


Et tu voit une autre utilité à un opérateur de cast et un
constructeur de conversion que reconvertir ??


Sauf qu'on ne veut pas que les conversions se font n'importe
où, sans qu'on se rende compte. Ce qu'il lui faut, ce sont
des conversions explicites.

Aussi, en passant, les types dans son exemple était bool et
int. Comment fais-tu à leur donner une conversion implicite
de et en std::string ?

À sa place, je jetterais un coup d'oeil du côté boost::any
ou boost::lexical_cast.


Je suis actuellement entrain de regarder à boost::any, car
c'est Fabien LE LEZ qui en a parlé lors d'un de mes précédents
posts.

La raison pour laquelle je voulais convertir tous les types de
bases vers un std::string, est que cela me permettait de créer
une std::map contenant mes préférences et ensuite sauver dans
un fichier text au format INI ou XML. Ou voir même dans une
base de données.


C'est ce dont je me doutais un peu. Dans ce cas-là (mais c'est
largement une question de goût personnel, je crois), j'aurais
tendance à garder des chaînes dans le map, plutôt que des
boost::any, et de faire le transtypage (éventuellement à l'aide
de boost::lexical_cast) lors de l'insertion et de l'extraction.

ou alors j'ai rien compris aux templates.


Ça n'a pas le moindre début de commencement de rapport avec
les templates, les conversions. Elles se font par le biais
de de méthodes parfaitement spécifiques, dans les classes.



Tu arrives à surcharger le type bool ou int au point tel qu'il
t'est possible de créer une méthode de transtypage avec les
operator bool (), int (), etc... ?


Bien sûr. À l'insertion, évidemment, il n'y a aucun problème :
une fonction membre template, instantiée sur le type que
l'utilisateur veut insérer, fait l'affaire. Pour l'extraction,
ce qu'il faut, c'est une fonction non templatée qui renvoie un
Proxy. On se rétrouve donc avec quelque chose comme :

class Table
{
public:
template< typename T >
void put( std::string const& key,
T const& value )
{
myMap.insert(
Map::value_type(
key,
boost::lexical_cast< std::string >( value ) ) ) ;
}

Proxy get( std::string const& key ) const
{
Map::const_iterator elem = myMap.find( key ) ;
if ( elem == myMap.end() ) {
// Erreur (probablement un throw)...
} else {
return Proxy( elem->second ) ;
}
}
// ...

} ;

Avec une classe Proxy (en général, je me sers d'une classe
embriquée pour ça) :

class Proxy
{
public:
explicit Proxy( std::string const& value )
: myValue( value )
{
}

template< typename T >
operator T() const
{
return boost::lexical_cast< T >( myValue ) ;
}

private:
std::string myValue ;
} ;

Le truc, évidemment, c'est que quand tu écris :

bool t = table.get( cle ) ;

le compilateur se trouve avec un Proxy, or qu'il veut un bool.
Il cherche donc une conversion, ce que fournit l'operator T.

Pas forcement. Elles se font surtout par des opérateurs de
conversion, du genre static_cast ou dynamic_cast. Ou des
templates conçus sur le même modèle, comme
boost::lexical_cast.


Je vais aller regarder du côté de boost::lexical_cast dès ce
soir.


C'est en tout cas une bonne inspiration. Mais l'implémentation
n'en est pas difficile (il se base sur [io]stringstream), et je
ne sais pas comment il traite les erreurs ; c'est tout à fait
possible que tu préfère le faire à la main, pour un meilleur
gestion des erreurs.

Vérifie bien aussi les conversions std::string->std::string --
c'est un cas où les opérateurs >> et << ne permet pas un
aller-retour. Je crois que boost::lexical_cast ait des
spécialisations pour ce cas-ci ; sinon, c'est à toi de les faire
pour Table::get et Proxy::operator T(). (Dans mon cas,
l'insertion était nettement plus complexe. J'ai donc fourni un
put explicit pour les chaînes, que j'appelais dans le put
templaté.)

--
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
Pierre THIERRY
Le Mon, 09 May 2005 08:50:20 -0700, kanze a écrit :
Jusqu'ici, je n'ai jamais trouvé un cas où la conversion
bidirectionnelle implicite était une bonne chose.


Dans ce cas, il suffit de se servir du mot-clef explicit, et on évite
les conversions implicites non prévues par le programmeur, non ?

Explicitement,
Nowhere man
--

OpenPGP 0xD9D50D8A

Avatar
Pierre THIERRY
Le Mon, 09 May 2005 20:09:48 +0200, Stephane Wirtel a écrit :
Tu arrives à surcharger le type bool ou int


À ma connaissance, on ne peut pas « surcharger » un type...

il t'est possible de créer une méthode de transtypage avec les
operator bool (), int (), etc... ?


Ben c'est le but de ces opérateurs. S'il existe un type _T, tu peux
ajouter à n'importe quelle de tes classes la méthode :

operator _T()

qui sera utilisée quand une conversion de ta classe vers _T est
nécessaire. Pour l'autre sens, soit tu peut mettre un opérateur de
conversion dans l'autre type, s'il est une classe dont tu as la
maîtirse, soit tu colles un constructeur de conversion :

MaClasse(_T)

Si tu veux éviter que ces conversions aient lieu implicitement, tu
utilises le mot-clef explicit. Tu pourras par exemple te servir de
static_cast pour déclencher les conversions.

Brièvement,
Nowhere man
--

OpenPGP 0xD9D50D8A

Avatar
kanze
Pierre THIERRY wrote:
Jusqu'ici, je n'ai jamais trouvé un cas où la conversion
bidirectionnelle implicite était une bonne chose.


Dans ce cas, il suffit de se servir du mot-clef explicit, et
on évite les conversions implicites non prévues par le
programmeur, non ?


Ça marche pour les constructeurs, mais on ne peut pas déclarer
un opérateur de conversion implicite.

En général, j'évite des conversions implictes, sauf dans
certains cas bien précis, comme les proxy.

--
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
Michel Michaud
Dans le message ,
Les deux bouquins de Delannoy sur le C++ sont très bien, par
exemple.




N.B. Ce n'est pas moi qui a dit ça... J'ai plutôt ajouté :

Il les a récrits récemment ?


J'ai respectivement la 5ème édition mise à jour (2000) et la 2ème
édition mise à jour et augmentée (2001) du cours et des exercices.


Il faudrait que je vérifie, mais ça me semble bien vieux et ça doit
correspondre à ceux que je ne suis pas seul à trouver très loin de
« très bien ».

[...]
N'en ayant pas lu d'autre, je ne peux pas comparer...


Je ne suis pas certain que ce soit nécessaire pour voir ce qui
cloche. Il suffit de le lire attentivement (et encore...).

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



Avatar
kanze
Michel Michaud wrote:
Dans le message
, Pierre
Les deux bouquins de Delannoy sur le C++ sont très bien, par
exemple.




N.B. Ce n'est pas moi qui a dit ça... J'ai plutôt ajouté :

Il les a récrits récemment ?


J'ai respectivement la 5ème édition mise à jour (2000) et la
2ème


édition mise à jour et augmentée (2001) du cours et des
exercices.



Il faudrait que je vérifie, mais ça me semble bien vieux et ça
doit correspondre à ceux que je ne suis pas seul à trouver
très loin de « très bien ».

[...]
N'en ayant pas lu d'autre, je ne peux pas comparer...


Je ne suis pas certain que ce soit nécessaire pour voir ce qui
cloche. Il suffit de le lire attentivement (et encore...).


Pour toi, peut-être. Si on ne connaît pas du tout le C++, est-ce
qu'on reconnaît d'office qu'ils sont mauvais ? S'ils sont
malécrits, avec des fautes de français, peut-être. Mais si le
problème, c'est qu'ils sont bourrés d'erreurs, ou qu'ils
présentent des solutions qui sont loins de ce qu'on fait du
mieux en C++ (par exemple, utiliser des char[] et <string.h>),
est-ce que quelqu'un qui ne connaît pas le C++ va reconnaître
les faiblesses ?

--
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
Loïc Joly

Pour toi, peut-être. Si on ne connaît pas du tout le C++, est-ce
qu'on reconnaît d'office qu'ils sont mauvais ? S'ils sont
malécrits, avec des fautes de français, peut-être.


Je crois qu'en effet, un des problèmes de livres de Delanoy ou de
Schildt (l'équivalent anglais) est qu'il sont en général bien écrits,
assez clairs, et bourrés de faiblesses... S'ils étaient mal écrits, ils
tomberaient dans l'oubli et ne causeraient pas de problèmes.


Mais si le
problème, c'est qu'ils sont bourrés d'erreurs, ou qu'ils
présentent des solutions qui sont loins de ce qu'on fait du
mieux en C++ (par exemple, utiliser des char[] et <string.h>),
est-ce que quelqu'un qui ne connaît pas le C++ va reconnaître
les faiblesses ?


Au vu du nombre de critiques positives faites par les lecteurs de ces
livres, visiblement pas.

--
Loïc

Avatar
Michel Michaud
Dans le message ,
Michel Michaud wrote:
Dans le message
, Pierre
N'en ayant pas lu d'autre, je ne peux pas comparer...


Je ne suis pas certain que ce soit nécessaire pour voir ce qui
cloche. Il suffit de le lire attentivement (et encore...).


Pour toi, peut-être. Si on ne connaît pas du tout le C++, est-ce
qu'on reconnaît d'office qu'ils sont mauvais ?


Pierre semble participer activement à ce forum, ça me paraissait
suffisant pour penser qu'il sait certaines choses utiles pour voir
que le livre n'est pas si bien qu'il en parlait. Je n'ai pas dit que
ceux qui ne connaissent rien peuvent voir les problèmes, j'ai seulement
dit, à lui, qu'il n'est pas nécessaire d'avoir lu d'autres livres...
(bien sûr, ça peut aider !)

S'ils sont
malécrits, avec des fautes de français, peut-être. Mais si le
problème, c'est qu'ils sont bourrés d'erreurs, ou qu'ils
présentent des solutions qui sont loins de ce qu'on fait du
mieux en C++ (par exemple, utiliser des char[] et <string.h>),
est-ce que quelqu'un qui ne connaît pas le C++ va reconnaître
les faiblesses ?


Bien sûr que non, mais s'il lit les messages et qu'il voit que
personne ne parle de ce qu'il a lu et qu'il semble y avoir de
meilleures solutions, c'est différent.

En fait, même si tu lis plusieurs livres, tu ne peux pas savoir s'ils
sont bons, alors ça n'aide pas vraiment... Par contre, lire ce forum
(ou d'autres) permet de voir divers avis, avec des discussions pour
les critiquer, ce qui finalement permet de connaître « la vérité »
(ou au moins un certain consensus).

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



Avatar
Pierre THIERRY
Le Sun, 22 May 2005 12:15:00 -0400, Michel Michaud a écrit :
Pierre semble participer activement à ce forum, ça me paraissait
suffisant pour penser qu'il sait certaines choses utiles pour voir que
le livre n'est pas si bien qu'il en parlait.


C'est assez délicat. On a facilement la tentation de croire que ce qu'on
a lu est exhaustif. Et les posts sur ce forum sont de qualité très
variée, et il faut là aussi faire le tri.

Le Delannoy, par exemple, ne mentionne pas du tout les spécialisations
de patrons de type 'template<> foo()'. Lorsque j'en ai vu sur le forum,
j'ai véritablement cru à une incompréhension du principe des templates
(je n'avais peut-être pas totalement tort, néanmoins...).

En fait, même si tu lis plusieurs livres, tu ne peux pas savoir s'ils
sont bons, alors ça n'aide pas vraiment...


Néanmoins, certaines échelles ne sont pas équivalentes. Un livre peut
être très peu pédagogique, mais parfaitement exact. Un autre limpide
pour le débutant, mais incomplet ou inexact.

Le premier, quand on le lit et le relit, ne devrait pas mener à trop de
malentendus et de fausses connaissances. Le deuxième présente plus de
risques, à long terme, si on le garde comme référence.

Pour ma part, je ne tarderai pas à acheter TC++PL pour cette raison.

Bibliographiquement,
Nowhere man
--

OpenPGP 0xD9D50D8A

1 2 3 4