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

pb de conversion en std::string

23 réponses
Avatar
MGN
mon problème est simple.
J'ai un modèle de classe

template<class T>
modele
{
// blablabla...

std::string display(void) const;
};

et dedans j'ai une méthode display qui fournit des renseignements sur le
contenu de modele (je simplifie pour aller à l'essentiel)
Ma question : y-a-t-il un moyen de savoir si l'opérateur de conversion
(std::string) est défini pour les objets de la classe T ?
Actuellement, la conversion est tentée à la compilation et modele<T> n'est
pas compilé si cette conversion n'est pas possible.
Je voudrais que la conversion soit testée à l'exécution...
Est-ce que c'est possible ?
J'espère avoir été clair ...

10 réponses

1 2 3
Avatar
Fabien LE LEZ
On Thu, 12 Oct 2006 22:13:30 +0200, "MGN" :

Ma question : y-a-t-il un moyen de savoir si l'opérateur de conversion
(std::string) est défini pour les objets de la classe T ?


En gros, tu voudrais faire un truc du style

template<class T>
struct modele
{
T un_T;
std::string display() const
{
if (T_a_un_operateur_de_conversion)
{
return std::string (un_T);
}
else
{
throw "Conversion impossible";
}
}
};

C'est bien ça ?

Avatar
Fabien LE LEZ
On Thu, 12 Oct 2006 22:13:30 +0200, "MGN" :

Ma question : y-a-t-il un moyen de savoir si l'opérateur de conversion
(std::string) est défini pour les objets de la classe T ?

Je voudrais que la conversion soit testée à l'exécution...


"Modern C++ design" (Alexandrescu), section 2.7 :

typedef char EstConvertible;
class PasConvertible { char dummy[2]; };

EstConvertible Test (std::string);
PasConvertible Test (...);

template <class T> struct EstConvertibleEnString
{
static bool operator ()
{
return sizeof (Test (T())) == sizeof (EstConvertible);
}
};


struct Avec
{ operator std::string() const; };

struct Sans
{ };

int main()
{
std::cerr << EstConvertibleEnString<Avec>()() << "n"
<< EstConvertibleEnString<Sans>()() << "n";
}



Note que tout est évalué à la compilation (comme toujours avec les
templates). Mais ça te donne un booléen, dont tu peux te servir à
l'exécution.

Avatar
Fabien LE LEZ

template <class T> struct EstConvertibleEnString
{
static bool operator ()


Gloups... Erreur ici ! À remplacer par :
bool operator()() const

{
return sizeof (Test (T())) == sizeof (EstConvertible);


En fait, je ne sais pas pourquoi j'ai créé une classe ici. Une
fonction template aurait aussi bien convenu (enfin, je crois).

Avatar
Fabien LE LEZ
Ma question : y-a-t-il un moyen de savoir si l'opérateur de conversion
(std::string) est défini pour les objets de la classe T ?

Je voudrais que la conversion soit testée à l'exécution...


"Modern C++ design" (Alexandrescu), section 2.7 :


[Y'a que moi, sur ce thread !?]

Petite précision : le code donné ici fonctionne si un T est
convertible en un std::string. Il répond "true" avec T == char*.

S'il faut vraiment tester, à l'exécution (i.e. le code doit
impérativement compiler), si "T::operator std::string() const" existe,
ça risque d'être plus compliqué.


Avatar
kanze
Fabien LE LEZ wrote:
Ma question : y-a-t-il un moyen de savoir si l'opérateur de
conversion (std::string) est défini pour les objets de la
classe T ?

Je voudrais que la conversion soit testée à l'exécution...


"Modern C++ design" (Alexandrescu), section 2.7 :


[Y'a que moi, sur ce thread !?]


Ton posting indique 3 heures du mat'. C'est sûr qu'à cette
heure-là, je n'y suis pas.

Petite précision : le code donné ici fonctionne si un T est
convertible en un std::string. Il répond "true" avec T ==
char*.

S'il faut vraiment tester, à l'exécution (i.e. le code doit
impérativement compiler), si "T::operator std::string() const"
existe, ça risque d'être plus compliqué.


Qu'une classe ait une conversion en std::string ou non, ça ne
change pas lors de l'exécution. C'est bien connu déjà à la
compilation.

Ceci dit, je me méfierais beaucoup d'une telle classe. Des
opérateurs de conversion ont leur utilité dans des cas bien
précis, mais une conversion implicite en std::string, ça me
semble chercher les ennuis : des ambiguïtés ou des erreurs non
détecter par le compilateur. C'est à éviter dans le cas général.

En fait, l'idiome « standard » pour convertir un objet en
texte, c'est de fournir un opérateur <<.

--
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
Marc G
S'il faut vraiment tester, à l'exécution (i.e. le code doit
impérativement compiler), si "T::operator std::string() const" existe,
ça risque d'être plus compliqué.
en fait, c'est une question plus théorique que pratique.

Comme tu dis, avec les templates, tout se règle à la compilation et ta
solution me convient très bien.
J'ai 2 petites questions :
1) pourquoi operator()() et pas operator() simplement ?
2) Pas convertible Test(...); //<- je croyais qu'il fallait au moins
définir un paramètre dans les fonctions avec une liste de paramètres
variable...
En tout cas, merci pour ta réponse.

Avatar
Marc G
j'ai mis en place ta solution avec une fonction template

template<class T>
bool EstConvertibleEnString()
{
T t;
return sizeof(t)==sizeof(EstConvertible);
}
nota : je ne peux pas écrire sizeof(T()), mon compilo n'apprécie pas (pb
habituel de passage par référence non constante je suppose)

mais il me reste un (gros) problème
Qd j'écris :
if (!EstConvertibleEnString<T>())
flux<<"pas convertible"<<"n";
else
flux<<std::string(t)<<"n";
mon compilateur refuse de compiler la dernière ligne si l'objet n'est pas
convertible :-), ce qui est en fait assez normal...
En fait, ça marche bien si l'objet est convertible
Tu as une idée ?
Avatar
Marc G
mais il me reste un (gros) problème
Qd j'écris :
if (!EstConvertibleEnString<T>())
flux<<"pas convertible"<<"n";
else
flux<<std::string(t)<<"n";
mon compilateur refuse de compiler la dernière ligne si l'objet n'est pas
convertible :-), ce qui est en fait assez normal...


j'ai trouvé une solution, dans le même esprit que la fonction TestConversion
que tu as définie

std::string to_string(std::string s) { return s;}
std::string to_string(...) { return "";}

if (!EstConvertibleEnString<T>())
flux<<"pas convertible"<<"n";
else
flux<< to_string(t)<<"n";

et ça marche cette fois-ci !
merci beaucoup pour ton aide.

Avatar
Sylvain Togni
Marc G wrote:, :

mais il me reste un (gros) problème
Qd j'écris :
if (!EstConvertibleEnString<T>())
flux<<"pas convertible"<<"n";
else
flux<<std::string(t)<<"n";
mon compilateur refuse de compiler la dernière ligne si l'objet n'est pas
convertible :-), ce qui est en fait assez normal...


j'ai trouvé une solution, dans le même esprit que la fonction TestConversion
que tu as définie

std::string to_string(std::string s) { return s;}
std::string to_string(...) { return "";}

if (!EstConvertibleEnString<T>())
flux<<"pas convertible"<<"n";
else
flux<< to_string(t)<<"n";

et ça marche cette fois-ci !


Encore plus simple :

std::string to_string(std::string const& s) {return s;}
std::string to_string(...) {return "pas convertible";}

flux << to_string(t) << 'n';

--
Sylvain Togni


Avatar
Marc G
on peut aussi faire un truc du genre
bool to_string(std::string s) { return true;}
bool to_string(...) { return false;}
pour savoir à l'exécution si la conversion est possible
nota :
quand j'écris
std::string to_string(std::string const& s) {return s;}
la référence pose problème avec mon compilo (BCB6)
si je fais par exemple
std::ostringstream flux;
flux<<to_string(un_objet)<<"n";
en fait ça plante :-)
je pense que c'est dû au fait qu'il y a d'abord une conversion de l'objet en
une string qui est détruite qd on appelle to_string (donc il faut
impérativement passer une copie)
Qu'en penses-tu ?
Marc
1 2 3