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
Pierre THIERRY
Le Mon, 18 Apr 2005 19:57:57 +0200, Stephane Wirtel a écrit :
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...";
}


Il semble que tu n'aies pas bien saisi la spécialistation de patrons de
fonctions... Ici ton patron ne contient aucun code, donc tu sembles
avoir besoin de surdéfinition, pas de patrons. De plus, on ne spécialise
pas un patron avec le mot clef template.

Le patron sert à appliquer un alogrithme strictement identique, au type
près, à des objets de types différents. Le compilateur créera des
instances du patron lorsqu'il en rencontrera le besoin. Exemple :

template<class T> T mediane(T a, T b, T c)
{
T temp1, temp2;
if (a <= b) {
temp1 = b; temp2 = a;
} else {
temp1 = a; temp2 = b;
}
if (temp1 > c) {
temp1 = c;
}
if (temp1 < temp2) {
temp1 = temp2;
}
return temp1;
}

Avec ça, si tu utilises, sans déclaration ou définition supplémentaire,
la fonction mediane sur n'importe quel type possédant les opérateurs '=',
'>', '<' et '<=', le compilateur générera une fonction appropriée.

Et si pour un type particulier, le traitement est différent, tu
spécialise :

TypeBizarre mediane(TypeBizarre a, TypeBizarre b, TypeBizarre c)
{
return a->fonction_bizarre(b, c);
}

Si l'algo est différent pour chacun des types dont tu vas te servir,
alors pas besoin de patrons. Tu écris la fonction normalement pour
chacun des types, c'est juste de la surdéfinition.

De plus, s'essayer aux particularités du C++ est louable, mais si tu
veux apprendre à manipuler toutes les possibilités du C++, fais-le dans
des conditions où c'est vraiment utile, ou tu risques d'associer
certaines solutions aux mauvais problèmes.

Prends un cours de C++ qui contient des exercices, c'est encore la voie
royale. Les deux bouquins de Delannoy sur le C++ sont très bien, par
exemple.

Pédagogiquement,
Nowhere man
--

OpenPGP 0xD9D50D8A

Avatar
Michel Michaud
Dans le message ,
Prends un cours de C++ qui contient des exercices, c'est encore la
voie royale. Les deux bouquins de Delannoy sur le C++ sont très
bien, par exemple.


Il les a récrits récemment ? Sinon « sont très bien » n'est pas le
commentaire qu'on a le plus souvent indiqué sur ce forum...

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

Avatar
Stephane Wirtel
J'ai ré-écrit complètement mes méthodes qui permettaient de convertir un
type vers un std::stringstream, que je reconverti vers un std::string.

Voici le code des méthodes.

template <class TypeData> std::string TranslateToString (TypeData pValue) {
std::stringstream inputStream;
inputStream << pValue;
return inputStream.str ();
}

template <class TypeData> TypeData StringTo (const std::string& pValue) {
std::stringstream iss (pValue, std::istringstream::in);
TypeData data;
iss >> data;
return data;
}

L'utilité de ce code était de stocker la valeur d'une variable de type
différent vers un std::string dans une std::map. Et lors de la lecture de
la variable, une conversion était faite dans le type d'origine de la
variable.

Maintenant, je vais essayer d'employer boost::any ou de créer ma propre
classe pour stocker des variables de types différents dans une std::map.
Sans devoir faire la conversion en std::string, ce qui me donnera la
possiblité de ne pas perdre d'information lors d'une conversion
déffectueuse.
Avatar
Pierre THIERRY
Le Sat, 07 May 2005 23:42:07 -0400, Michel Michaud a écrit :
Les deux bouquins de Delannoy sur le C++ sont très bien, par exemple.
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.

Sinon « sont très bien » n'est pas le commentaire qu'on a le plus
souvent indiqué sur ce forum...


Le cours s'adresse à quelqu'un qui connaît le C, et opère le passage C
vers C++. La progression pédagogique est bien pensée, et on produit tout
de suite du code fonctionnel sans se prendre la tête. Notamment, on voit
le strict nécessaire quant à l'utilisation de cout/cin dès le début,
pour s'en servir tout au long du bouquin, les flux n'étant réellement
abordés que beaucoup plus tard.

Quand, après n'avoir pas programmé pendant longtemps, je me suis remis
au C++, je n'ai eu aucun mal à m'y retrouver, le bouquin se resurvole
aisément, pour se rafraichir la mémoire.

Néanmoins, comme il fait le passage C vers C++, il n'est pas exhaustif,
et n'est donc pas forcément le meilleur choix comme référence à garder
sous la main.

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

Philologiquement,
Nowhere man
--

OpenPGP 0xD9D50D8A


Avatar
Pierre THIERRY
Le Sun, 08 May 2005 10:51:27 +0200, Stephane Wirtel a écrit :
J'ai ré-écrit complètement mes méthodes qui permettaient de convertir
un type vers un std::stringstream, que je reconverti vers un
std::string.


Ce ne serait pas plus simple de doter tes classes de deux cast, vers et
depuis std::string ? On fait ça respectivement avec :

- operator std::string(),
- MaClasse(const &std::string).

Simplement,
Nowhere man
--

OpenPGP 0xD9D50D8A

Avatar
Stephane Wirtel
Pierre THIERRY wrote:

Le Sun, 08 May 2005 10:51:27 +0200, Stephane Wirtel a écrit :
J'ai ré-écrit complètement mes méthodes qui permettaient de convertir
un type vers un std::stringstream, que je reconverti vers un
std::string.


Ce ne serait pas plus simple de doter tes classes de deux cast, vers et
depuis std::string ? On fait ça respectivement avec :

- operator std::string(),
- MaClasse(const &std::string).
Je ne pense pas que cela puisse m'aider, simplement que je veux intégrer

dans une map des types différents reconvertit en std::string.

Cela m'aide pour écrire ceci :
int port = Settings.Read ("PORT", 25);
bool isactive = Settings.Read ("ISACTIVE", false);

ou alors j'ai rien compris aux templates.

Simplement,
Nowhere man


--
Stephane Wirtel


Avatar
Pierre THIERRY
Le Sun, 08 May 2005 22:13:09 +0200, Stephane Wirtel a écrit :
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 ??

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.

Brièvement,
Nowhere man
--

OpenPGP 0xD9D50D8A

Avatar
kanze
Pierre THIERRY wrote:
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...";
}


Il semble que tu n'aies pas bien saisi la spécialistation de
patrons de fonctions... Ici ton patron ne contient aucun code,
donc tu sembles avoir besoin de surdéfinition, pas de
patrons. De plus, on ne spécialise pas un patron avec le mot
clef template.


J'ai plutôt l'impression que c'est toi qui n'as pas compris.
Qu'est-ce qu'il doit mettre dans le template de base ? (En fait,
je me serais contenté d'une declaration, sans définition. Pour
avoir une erreur lors de l'addition de liens, si j'essayais à
mon servir.)

En ce qui concerne la syntaxe de la spécialisation, ce qu'il a
fait est correct. Même si c'est possible que certains
compilateurs acceptent d'autres syntaxes aussi, pour des raisons
historiques.

Le patron sert à appliquer un alogrithme strictement
identique, au type près, à des objets de types différents.


C'est une des utilisations. Plus généralement, les templates
servent à la spécification du code qui doit être généré
automatiquement, par le compilateur. Et les utilisations des
templates dont on ne se sert que des spécialisations explicites
existent bel et bien -- il y en a même dans la norme
(std::char_traits, par exemple).

[...]
Si l'algo est différent pour chacun des types dont tu vas te
servir, alors pas besoin de patrons.


Sauf si tu veux t'en servir à l'intérieur d'un autre template.
Pense à des choses comme std::numeric_limits, par exemple.

Tu écris la fonction normalement pour chacun des types, c'est
juste de la surdéfinition.


Cette solution peut servir dans certains cas. Mais pas toujours.

De plus, s'essayer aux particularités du C++ est louable, mais
si tu veux apprendre à manipuler toutes les possibilités du
C++, fais-le dans des conditions où c'est vraiment utile, ou
tu risques d'associer certaines solutions aux mauvais
problèmes.

Prends un cours de C++ qui contient des exercices, c'est
encore la voie royale. Les deux bouquins de Delannoy sur le
C++ sont très bien, par exemple.


Ce n'est pas ce que j'ai entendu dire.

Pour bien apprendre le C++, il faut bien plus d'un seul livre.
Pour les débutants, je ne sais pas trop conseiller, parce que je
n'ai pas lu un livre pour débuttants dépuis bien longtemps.
(Moi-même, j'ai appris le C++ de la première édition de
Stroustrup. Je suppose donc que l'édition plus récente est bien
aussi. Mais c'était un livre pour quelqu'un qui connaissait déjà
un peu l'informatique.)

En ce qui concerne les templates, il y a le Vandevoorte et
Josuttis, qui est non seulement exceptionnellement complet, mais
aussi exceptionnellement lisible.

--
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
kanze
Pierre THIERRY wrote:
J'ai ré-écrit complètement mes méthodes qui permettaient de
convertir un type vers un std::stringstream, que je
reconverti vers un std::string.


Ce ne serait pas plus simple de doter tes classes de deux
cast, vers et depuis std::string ? On fait ça respectivement
avec :

- operator std::string(),
- MaClasse(const &std::string).


C'est une bonne recette pour des ambiguïtés dans la résolution
des surcharges, sans parler des problèmes de lisibilité pour
celui qui te suit.

Jusqu'ici, je n'ai jamais trouvé un cas où la conversion
bidirectionnelle implicite était une bonne chose. (Y compris
dans le langage même -- si un int se convertit implicitement en
double, un double ne doit pas se convertit implicitement en
int.)

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

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.


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.

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.

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


1 2 3 4