OVH Cloud OVH Cloud

template et const

22 réponses
Avatar
Fabien SK
Bonjour,

Je désire écrire une classe permettant de manipuler un sous-ensemble
d'un buffer texte. Cette classe n'aura comme donnée membre que le
pointeur sur la partie du buffer et la taille du buffer à manipuler.
Exemple:

class InBuffField
{
public:
InBuffField(char *pbuff, size_t len);

char* Get();
size Len()const;
void Trim(char c=' ');
bool Compare(InBuffField &other)const;
bool CompareTrim(InBuffField &other)const;
// [...]
private:
char *m_pBuff;
size_t m_Len;
};

char *pbuff = "TOTO 12345 TATA";
InBuffField field(pbuff, 6);
field.TrimRight();
std::cout << field.Length() << std::endl; // affiche '4'
std::cout.write(field.Get(), field.Length());

Mon problème est que je veux supporter dans cette classe à la fois les
pointeurs vers des "char*" et des "const char*". La version avec "const
char*" n'aurait donc pas accès à des méthode telles que "Replace".

Je dois donc décider d'un type pour "m_pBuff". Je ne vois pas comment
faire, à part en faisant une classe template pouvant prendre comme type
"char" ou "const char". Par contre après, ça va me poser des problèmes
pour mes méthodes "Compare" car elles vont devoir comparer des objets de
type:
- InBuffField<char>
- InBuffField<const char>

J'ai pensé à la conversion automatique (fonction membre):

operator InBuffField<const _CH>()const
{
return InBuffField<const _CH>(m_pBuff, m_Len);
}

Mais je sens que ça va me mener à des effets aussi indésirables
qu'inattendus.

Si vous avez une idée de design, je suis preneur.
Merci de votre attention

Fabien

10 réponses

1 2 3
Avatar
Fabien LE LEZ
On Wed, 13 Aug 2003 17:30:09 +0200, Fabien SK <fabsk+
wrote:

char *pbuff = "TOTO 12345 TATA";


Il me semble que ceci est interdit, ou du moins fortement
déconseillé : tu risques de modifier une chaîne constante via ton
"char*".
Au fait, es-tu vraiment obligé d'utiliser des char* ? Ça serait
tellement plus facile avec std::string...


--
Tout sur fr.* (FAQ, etc.) : http://www.usenet-fr.net/fur/
et http://www.aminautes.org/forums/serveurs/tablefr.html
Archives : http://groups.google.com/advanced_group_search
http://www.usenet-fr.net/fur/usenet/repondre-sur-usenet.html

Avatar
Fabien SK
Fabien LE LEZ wrote:

On Wed, 13 Aug 2003 17:30:09 +0200, Fabien SK <fabsk+
wrote:


char *pbuff = "TOTO 12345 TATA";



Il me semble que ceci est interdit, ou du moins fortement
déconseillé : tu risques de modifier une chaîne constante via ton
"char*".
Au fait, es-tu vraiment obligé d'utiliser des char* ? Ça serait
tellement plus facile avec std::string...



Merci de ta réponse

Au temps pour moi, c'est pour l'exemple. Il aurait été plus valide de
faire (toujours pour l'exemple):

char pbuff[256];
strcpy(pbuff, "TOTO 12345 TATA");

Dans le soft sur lequel je travaille (et dont les APIs ne peuvent pas
bouger), je dois manipuler des buffers de texte ayant des champs à des
offsets bien définis. Si j'utilise des "std::string", ça implique:
- que je vais devoir remettre à jour après coup le buffer d'où viennent
les données
- que je vais devoir allouer de la mémoire à chaque manipulation, ce qui
va affecter les perfs.

Mon idée était de faire une classe pour encapsuler les champs, ce qui
permet:
- de ne pas réinventer la roue à chaque fois qu'on veut faire une manip
sur un champ (les boucles "while" pour enlever les espaces...)
- que le programmeur ne se trompe pas avec les offsets

De plus, nombre de fonctions de manipulation peuvent être écrites avec
les fonctions STL d'algorithm, ce qui rend l'implémentation simple.

Voila donc pourquoi je cherche une solution de ce type.

Fabien


Avatar
Fabien LE LEZ
On Wed, 13 Aug 2003 17:30:09 +0200, Fabien SK <fabsk+
wrote:

Mon problème est que je veux supporter dans cette classe à la fois les
pointeurs vers des "char*" et des "const char*". La version avec "const
char*" n'aurait donc pas accès à des méthode telles que "Replace".


Encore une fois, mieux vaudrait utiliser std::string...
Mais bon, voici comment je ferais :

class InBuffField_base
{
InBuffField_base (size_t len);
size_t Len()const;
bool Compare (InBuffField_base const &other)const;

protected:
size_t m_Len;
private:
virtual char const* Get_const()= 0;
};

class InBuffField_const
{
public:
InBuffField_const (char const* buf, size_t l)
: InBuffField_base (l), m_pBuff (buf) {}
private:
virtual char const* Get_const() { return m_pBuff; }
char const *m_pBuff:
};

class InBuffField: public InBuffField_base
{
public:
InBuffField (char *pbuff, size_t len);
: InBuffField_base (len), m_pBuff (pbuff) {}
void Trim (char c= ' ');
private:
char* m_pBuff;
virtual char const* Get_const() { return m_pBuff; }
};

Toutes les fonctions qui utilisent des "const char*" (Compare par
exemple) sont dans InBuffField_base (et utilisent Get_const() pour
obtenir le pointeur) ; toutes celles qui utilisent un "char*" sont
dans InBuffField, et utilisent directement le pointeur "m_pBuff".
Tu vas sans doute rajouter des fonctions dans InBuffField_base et dans
InBuffField, mais vraisemblablement pas dans InBuffField_const.


--
Tout sur fr.* (FAQ, etc.) : http://www.usenet-fr.net/fur/
et http://www.aminautes.org/forums/serveurs/tablefr.html
Archives : http://groups.google.com/advanced_group_search
http://www.usenet-fr.net/fur/usenet/repondre-sur-usenet.html

Avatar
Fabien SK
Fabien LE LEZ wrote:

On Wed, 13 Aug 2003 17:30:09 +0200, Fabien SK <fabsk+
wrote:


Mon problème est que je veux supporter dans cette classe à la fois les
pointeurs vers des "char*" et des "const char*". La version avec "const
char*" n'aurait donc pas accès à des méthode telles que "Replace".



Encore une fois, mieux vaudrait utiliser std::string...
Mais bon, voici comment je ferais :

[...] le code



Merci beaucoup. Pourquoi n'y ai-je pas pensé... Surement parce que je
n'étais pas parti sur une solution avec l'héritage.

Fabien


Avatar
Fabien SK
Fabien LE LEZ wrote:

Au temps pour moi, c'est pour l'exemple. Il aurait été plus valide de
faire (toujours pour l'exemple):

char pbuff[256];
strcpy(pbuff, "TOTO 12345 TATA");



Berk... c'est du mauvais C :-/
Pour reprendre ton exemple en version "correcte", on écrirait

char machin[]= "TOTO 12345 TATA";


Ca m'a toujours titillé d'affecter dans un tableau de char une chaîne
qui dans le cas général est constante.


Avatar
drkm
Fabien SK <fabsk+ writes:

Fabien LE LEZ wrote:

Au temps pour moi, c'est pour l'exemple. Il aurait été plus
valide de faire (toujours pour l'exemple):

char pbuff[256];
strcpy(pbuff, "TOTO 12345 TATA");


Berk... c'est du mauvais C :-/

Pour reprendre ton exemple en version "correcte", on écrirait
char machin[]= "TOTO 12345 TATA";


Ca m'a toujours titillé d'affecter dans un tableau de char une chaîne
qui dans le cas général est constante.


C'est pourtant là l'intérêt. Tu n'affectes pas la chaîne au
tableau, tu initialises le tableau de caractères avec les caractères
de la chaîne constante. Tu te retrouve donc avec une « copie » de ta
chaîne : un tableau tout ce qu'il y a de plus modifiable.

Il s'agit en fait, pour les tableaux de caractères, d'une notation
alternative pour l'initialisation classique de tableaux.
L'initialisation ci-dessus est équivalente à :

char machin[] = {
'T' , 'O', 'T', 'O', ' ',
'1', '2', '3', '4', '5', ' ',
'T', 'A', 'T', 'A', ''
} ;

Mais qu'en est-il finalement de l'affectation initiale :

char * str = "..." ;

Je pensais comme Fabien (Le Lez) que cela était interdit. Il me
semble que cela était légal en C, et encore, plus en C99, mais pas en
C++. Juste ?

--drkm



Avatar
Fabien LE LEZ
On 14 Aug 2003 15:24:27 +0200, drkm wrote:

Mais qu'en est-il finalement de l'affectation initiale :

char * str = "..." ;

Je pensais comme Fabien (Le Lez) que cela était interdit. Il me
semble que cela était légal en C, et encore, plus en C99, mais pas en
C++. Juste ?


Je ne suis pas très sûr de moi sur la légalité de la chose. Ce qui est
certain, c'est la la modification du tableau est interdit. Ne pas
mettre le "const" à "char const*" est donc de l'obfuscation.


--
Tout sur fr.* (FAQ, etc.) : http://www.usenet-fr.net/fur/
et http://www.aminautes.org/forums/serveurs/tablefr.html
Archives : http://groups.google.com/advanced_group_search
http://www.usenet-fr.net/fur/usenet/repondre-sur-usenet.html

Avatar
Fabien LE LEZ
On Thu, 14 Aug 2003 15:46:45 +0200, Fabien SK <fabsk+
wrote:

j'aurais trouvé plus simple que les chaînes soientt toujours des "const
char*"


Chez moi, une chaîne est toujours "const char*" ou "std::string" :-)


--
Tout sur fr.* (FAQ, etc.) : http://www.usenet-fr.net/fur/
et http://www.aminautes.org/forums/serveurs/tablefr.html
Archives : http://groups.google.com/advanced_group_search
http://www.usenet-fr.net/fur/usenet/repondre-sur-usenet.html

Avatar
Fabien SK
Fabien LE LEZ wrote:
On Thu, 14 Aug 2003 15:46:45 +0200, Fabien SK <fabsk+
wrote:

j'aurais trouvé plus simple que les chaînes soientt toujours des "const
char*"


Chez moi, une chaîne est toujours "const char*" ou "std::string" :-)


Ah si la norme et les compilateurs étaient comme toi... :-) Ils
refuseraient:

"toto"[0] = 'a';

Mais bon, je radote


Avatar
Gabriel Dos Reis
drkm writes:

[...]

| Mais qu'en est-il finalement de l'affectation initiale :
|
| char * str = "..." ;

deprecated.

-- Gaby
1 2 3