J'ai quelques soucis de cohabitation de la classe "std::string" avec
le reste de mon code.
Soit le code suivant (non modifiable) :
#include <string>
// Classe abstraite pour tous les objets manipulés
struct node
{
virtual ~node() { }
};
// Classe abstraite pour une valeur
struct value : public node
{
};
// Classe abstraite pour un paramètre
struct param : public node
{
virtual const value& getValue() const = 0;
virtual void setValue(const value& val) = 0;
};
// Définition d'un paramètre générique (pour éviter d'avoir
// à réécrire une classe pour chaque type de valeur)
template <class TYPE>
struct genericParam : public node
{
const value& getValue() const
{ return (m_value); }
void setValue(const value& val)
{ m_value = dynamic_cast <TYPE&>(val); }
private:
TYPE m_value;
};
// Types de valeurs possibles
struct date : public value { };
struct charset : public value { };
// Types de paramètres possibles
struct dateParam : public genericParam <date> { };
struct charsetParam : public genericParam <charset> { };
J'aimerais ajouter un paramètre de type 'string' :
struct stringParam : public genericParam <std::string> { };
Evidemment, le code suivant ne compile pas ("std::string" n'hérite pas de
la classe "value") :
int main()
{
stringParam prm;
prm.getValue();
}
In member function `const value& genericParam<TYPE>::getValue() const
[with TYPE = std::string]': (...)
error: invalid initialization of reference of type 'const value&' from
expression of type 'const std::string'
Dès lors, pour résoudre mon problème, plusieurs solutions s'offrent à moi :
* créer une nouvelle classe "myString" héritant de la classe "std::string"
et de la classe "value" (héritage multiple) :
class myString : public std::string, public value
==> Abandonner l'idée car "std::string" n'est pas prévue pour être
dérivée (pas de destructeur virtuel).
* réécrire une classe "myString" implémentant toutes les fonctionnalités
de std::string (en gros, réinventer la roue...) :
==> Un peu lourd, solution de dernier recours.
* écrire une classe adapteur :
struct stringAdapter : public value
{
stringAdapter() { }
stringAdapter(const std::string& str) : m_str(str) { }
-- vmime, une bibliothèque C++ sous licence GPL pour parser et générer des messages au format MIME : http://www.sourceforge.net/projects/vmime/
Loïc Joly
Vincent Richard wrote:
* écrire une classe adapteur :
struct stringAdapter : public value [...]
Pourquoi ne pas en faire un fondamentalTypeAdapter templaté sur le type à adapter ? AMA, tu voudras un jour avoir des genericParam<int>.
Voyez-vous d'autres solutions à me proposer ? (sachant que je cherche à ne pas modifier les classes présentées en première partie : node, value, etc.)
Tu pourrais aussi spécialiser genericParam pour le type string, voire pour tous les types fondamentaux (même si c'est un peu plus dur à écrire dans ce cas...).
-- Loïc
Vincent Richard wrote:
* écrire une classe adapteur :
struct stringAdapter : public value
[...]
Pourquoi ne pas en faire un fondamentalTypeAdapter templaté sur le type
à adapter ? AMA, tu voudras un jour avoir des genericParam<int>.
Voyez-vous d'autres solutions à me proposer ? (sachant que je cherche à ne
pas modifier les classes présentées en première partie : node, value, etc.)
Tu pourrais aussi spécialiser genericParam pour le type string, voire
pour tous les types fondamentaux (même si c'est un peu plus dur à écrire
dans ce cas...).
Pourquoi ne pas en faire un fondamentalTypeAdapter templaté sur le type à adapter ? AMA, tu voudras un jour avoir des genericParam<int>.
Voyez-vous d'autres solutions à me proposer ? (sachant que je cherche à ne pas modifier les classes présentées en première partie : node, value, etc.)
Tu pourrais aussi spécialiser genericParam pour le type string, voire pour tous les types fondamentaux (même si c'est un peu plus dur à écrire dans ce cas...).
-- Loïc
Vincent Richard
Tu pourrais aussi spécialiser genericParam pour le type string, voire pour tous les types fondamentaux (même si c'est un peu plus dur à écrire dans ce cas...).
Je me trompe où la spécialisation n'est pas utilisable dans mon cas ?
Il ne faut pas perdre de vue que "genericParam" doit toujours dériver de la classe abstraite "param" qui oblige à définir les 2 fonctions :
qui sont justement celles qui posent problème (et qui ne dépendent pas du type générique).
Vincent
-- vmime, une bibliothèque C++ sous licence GPL pour parser et générer des messages au format MIME : http://www.sourceforge.net/projects/vmime/
Tu pourrais aussi spécialiser genericParam pour le type string, voire
pour tous les types fondamentaux (même si c'est un peu plus dur à écrire
dans ce cas...).
Je me trompe où la spécialisation n'est pas utilisable dans mon cas ?
Il ne faut pas perdre de vue que "genericParam" doit toujours dériver de la
classe abstraite "param" qui oblige à définir les 2 fonctions :
Tu pourrais aussi spécialiser genericParam pour le type string, voire pour tous les types fondamentaux (même si c'est un peu plus dur à écrire dans ce cas...).
Je me trompe où la spécialisation n'est pas utilisable dans mon cas ?
Il ne faut pas perdre de vue que "genericParam" doit toujours dériver de la classe abstraite "param" qui oblige à définir les 2 fonctions :
qui sont justement celles qui posent problème (et qui ne dépendent pas du type générique).
Vincent
-- vmime, une bibliothèque C++ sous licence GPL pour parser et générer des messages au format MIME : http://www.sourceforge.net/projects/vmime/
Loïc Joly
Vincent Richard wrote:
Tu pourrais aussi spécialiser genericParam pour le type string, voire pour tous les types fondamentaux (même si c'est un peu plus dur à écrire dans ce cas...).
Je me trompe où la spécialisation n'est pas utilisable dans mon cas ?
Il ne faut pas perdre de vue que "genericParam" doit toujours dériver de la classe abstraite "param" qui oblige à définir les 2 fonctions :
Dans ce que tu as écrit, genericParam dérive de node...
qui sont justement celles qui posent problème (et qui ne dépendent pas du type générique).
Je parle de spécialiser la classe dans son ensemble. Je ne vois pas de problèmes à écrire :
class stringAdapter{...};
template<> class genericParam<std::string> : public genericParam<stringAdapter> { };
L'avantage que je peux voir est que les utilisateurs peuvent alors écrire genericParam<string> et avoir l'équivalent d'un genericParam<stringAdapter>.
-- Loïc
Vincent Richard wrote:
Tu pourrais aussi spécialiser genericParam pour le type string, voire
pour tous les types fondamentaux (même si c'est un peu plus dur à écrire
dans ce cas...).
Je me trompe où la spécialisation n'est pas utilisable dans mon cas ?
Il ne faut pas perdre de vue que "genericParam" doit toujours dériver de la
classe abstraite "param" qui oblige à définir les 2 fonctions :
Dans ce que tu as écrit, genericParam dérive de node...
Tu pourrais aussi spécialiser genericParam pour le type string, voire pour tous les types fondamentaux (même si c'est un peu plus dur à écrire dans ce cas...).
Je me trompe où la spécialisation n'est pas utilisable dans mon cas ?
Il ne faut pas perdre de vue que "genericParam" doit toujours dériver de la classe abstraite "param" qui oblige à définir les 2 fonctions :
Dans ce que tu as écrit, genericParam dérive de node...
qui sont justement celles qui posent problème (et qui ne dépendent pas du type générique).
Je parle de spécialiser la classe dans son ensemble. Je ne vois pas de problèmes à écrire :
class stringAdapter{...};
template<> class genericParam<std::string> : public genericParam<stringAdapter> { };
L'avantage que je peux voir est que les utilisateurs peuvent alors écrire genericParam<string> et avoir l'équivalent d'un genericParam<stringAdapter>.
-- Loïc
Jean-Marc Bourguet
Vincent Richard writes:
class myString : public std::string, public value
==> Abandonner l'idée car "std::string" n'est pas prévue pour être dérivée (pas de destructeur virtuel).
Tu comptes detruire des instances a partir d'un pointeur vers std::string? (Je ne dis pas que c'est une bonne solution mais conteste la raison pour laquelle tu dis qu'elle n'est pas bonne).
Ce que propose Loic me semble pas mal.
A+
-- Jean-Marc FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html Site de usenet-fr: http://www.usenet-fr.news.eu.org
Vincent Richard <chere-loque.MARRE-DE-LA-PUB@wanadoo.fr.invalid> writes:
class myString : public std::string, public value
==> Abandonner l'idée car "std::string" n'est pas prévue pour être
dérivée (pas de destructeur virtuel).
Tu comptes detruire des instances a partir d'un pointeur vers
std::string? (Je ne dis pas que c'est une bonne solution mais
conteste la raison pour laquelle tu dis qu'elle n'est pas bonne).
Ce que propose Loic me semble pas mal.
A+
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
==> Abandonner l'idée car "std::string" n'est pas prévue pour être dérivée (pas de destructeur virtuel).
Tu comptes detruire des instances a partir d'un pointeur vers std::string? (Je ne dis pas que c'est une bonne solution mais conteste la raison pour laquelle tu dis qu'elle n'est pas bonne).
Ce que propose Loic me semble pas mal.
A+
-- Jean-Marc FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html Site de usenet-fr: http://www.usenet-fr.news.eu.org
Vincent Richard
Je me trompe où la spécialisation n'est pas utilisable dans mon cas ?
Il ne faut pas perdre de vue que "genericParam" doit toujours dériver de la classe abstraite "param" qui oblige à définir les 2 fonctions :
Dans ce que tu as écrit, genericParam dérive de node...
En effet, autant pour moi, c'est une erreur. La classe "genericParam" dérive bien bien de "param"...
Merci pour les idées.
Vincent
-- vmime, une bibliothèque C++ sous licence GPL pour parser et générer des messages au format MIME : http://www.sourceforge.net/projects/vmime/
Je me trompe où la spécialisation n'est pas utilisable dans mon cas ?
Il ne faut pas perdre de vue que "genericParam" doit toujours dériver de
la classe abstraite "param" qui oblige à définir les 2 fonctions :
Dans ce que tu as écrit, genericParam dérive de node...
En effet, autant pour moi, c'est une erreur.
La classe "genericParam" dérive bien bien de "param"...
Merci pour les idées.
Vincent
--
vmime, une bibliothèque C++ sous licence GPL pour parser et générer
des messages au format MIME : http://www.sourceforge.net/projects/vmime/