string::clear() vs string::resize( 0 ) vs string::erase( begin(), end() )
12 réponses
Aurelien Regat-Barrel
Bonjour,
Je cherche un moyen de réinitialiser la longueur d'une string à 0 sans
toucher à sa capacity().
Que dit la norme à ce propos ? Quel sont les influences de:
- clear()
- resize( 0 )
- erase( begin(), end() )
sur la valeur de capacity() ?
Tiens, ça fait longtemps que je n'en ai pas parlé. C'est pour ça qu'il existe Fallible<T> ; on renvoie Fallible< std::string >, et le tour est joué. C'est même plus robuste, puisque tout essai à accéder à la chaîne si la variable de contrôle est fausse donne une violation d'une assertion.
Ca a l'air intéressant J'ai trouvé ce lien: http://cpptips.hyperformix.com/cpptips/fallible y'aurait-t il mieux ?
Il y avait une implémentation complète dans ma bibliothèque, mais pour des raisons diverses, elle n'est pas en ligne actuellement. Sinon, je crois que le concepte est assez simple, et il y a même une implémentation dans la page que tu cites.
La seule chose à ajouter, réelement, c'est que depuis, j'ai ajouté une fonction membre :
template< typename T > T Fallible< T >::elseDefaultTo( T const& defaultValue ) { return isValid() ? value : defaultValue ; }
Aussi, une ou deux fois il m'est arrivé d'avoir besoin de plus d'informations dans le cas d'erreur. Alors, j'ai réécrit mon propre « fallible » à la main, plutôt que d'utiliser le template, avec une enum à la place du booléen, etc. Je n'y avais pas reflechi à l'époque, mais j'imagine qu'on pourrait faire la même chose de façon générique, avec des traits. Quelque chose du genre :
// --------------------------------------------------------------------------- // Contraints : // // Sur Value : // Supporte la copie, l'affectation, et la construction par // défaut. // // L'affectation d'une Value doit donner la garantie forte // par rapport aux exceptions. // // Sur Traits : // Définit tous les éléments définis dans // DefaultFallibleTraits. // // Sur Traits::StatusType : // Supporte la copie et l'affectation, sans risque // d'exception. // // Value et Traits::StatusType ne doivent pas être le même // type. // --------------------------------------------------------------------------- template< typename Value, typename Traits = DefaultFallibleTraits > class Fallible { typedef Traits::StatusType StatusType ;
public: explicit Fallible( StatusType validator = Traits::defaultInvalid() ) ; explicit Fallible( T const& value, StatusType validator = Traits::defaultValid() ) ; Fallible& operator=( T const& value ) ; Fallible& operator=( StatusType validator ) ; // Constructeur de copie, affectation par copie et // destructeur fournis par le compilateur...
bool isValid() const ; StatusType status() const ; T const& value() const ; T elseDefaultTo( T const& defaultValue ) const ;
private: // Attention : // L'ordre des déclarations ici est critique pour la // bonne gestion des exceptions. Lors d'une affectation, // il faut toujours que myValue soit affectée avant // myStatus ; sinon, si l'affectation de myValue lève une // exception, on risque d'avoir un état valid sans avoir // de valeur valide. (L'ordre des déclarations détermine // l'ordre des affectations dans l'opérateur // d'affectation générée par le compilateur.) // ----------------------------------------------------------------------- T myValue ; StatusType myStatus ; } ;
(Attention : je viens juste d'avoir l'idée ; le code ci-dessus n'est qu'une première esquisse, écrit dans une démi-heure, et jamais compilé. Il y a donc de fortes chances qu'il contient des erreurs. Mais ça doit donner une idée de ce qu'il faudrait.)
-- 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
Aurelien Regat-Barrel wrote:
Tiens, ça fait longtemps que je n'en ai pas parlé. C'est
pour ça qu'il existe Fallible<T> ; on renvoie Fallible<
std::string >, et le tour est joué. C'est même plus robuste,
puisque tout essai à accéder à la chaîne si la variable de
contrôle est fausse donne une violation d'une assertion.
Ca a l'air intéressant J'ai trouvé ce lien:
http://cpptips.hyperformix.com/cpptips/fallible y'aurait-t il
mieux ?
Il y avait une implémentation complète dans ma bibliothèque,
mais pour des raisons diverses, elle n'est pas en ligne
actuellement. Sinon, je crois que le concepte est assez simple,
et il y a même une implémentation dans la page que tu cites.
La seule chose à ajouter, réelement, c'est que depuis, j'ai
ajouté une fonction membre :
template< typename T >
T
Fallible< T >::elseDefaultTo( T const& defaultValue )
{
return isValid() ? value : defaultValue ;
}
Aussi, une ou deux fois il m'est arrivé d'avoir besoin de plus
d'informations dans le cas d'erreur. Alors, j'ai réécrit mon
propre « fallible » à la main, plutôt que d'utiliser le
template, avec une enum à la place du booléen, etc. Je n'y avais
pas reflechi à l'époque, mais j'imagine qu'on pourrait faire la
même chose de façon générique, avec des traits. Quelque chose du
genre :
//
---------------------------------------------------------------------------
// Contraints :
//
// Sur Value :
// Supporte la copie, l'affectation, et la construction
par
// défaut.
//
// L'affectation d'une Value doit donner la garantie forte
// par rapport aux exceptions.
//
// Sur Traits :
// Définit tous les éléments définis dans
// DefaultFallibleTraits.
//
// Sur Traits::StatusType :
// Supporte la copie et l'affectation, sans risque
// d'exception.
//
// Value et Traits::StatusType ne doivent pas être le même
// type.
//
---------------------------------------------------------------------------
template< typename Value, typename Traits = DefaultFallibleTraits >
class Fallible
{
typedef Traits::StatusType
StatusType ;
public:
explicit Fallible( StatusType validator
=
Traits::defaultInvalid() ) ;
explicit Fallible( T const& value,
StatusType validator
=
Traits::defaultValid() ) ;
Fallible& operator=( T const& value ) ;
Fallible& operator=( StatusType validator ) ;
// Constructeur de copie, affectation par copie et
// destructeur fournis par le compilateur...
bool isValid() const ;
StatusType status() const ;
T const& value() const ;
T elseDefaultTo( T const& defaultValue )
const ;
private:
// Attention :
// L'ordre des déclarations ici est critique pour la
// bonne gestion des exceptions. Lors d'une
affectation,
// il faut toujours que myValue soit affectée avant
// myStatus ; sinon, si l'affectation de myValue lève
une
// exception, on risque d'avoir un état valid sans
avoir
// de valeur valide. (L'ordre des déclarations
détermine
// l'ordre des affectations dans l'opérateur
// d'affectation générée par le compilateur.)
//
-----------------------------------------------------------------------
T myValue ;
StatusType myStatus ;
} ;
(Attention : je viens juste d'avoir l'idée ; le code ci-dessus
n'est qu'une première esquisse, écrit dans une démi-heure, et
jamais compilé. Il y a donc de fortes chances qu'il contient des
erreurs. Mais ça doit donner une idée de ce qu'il faudrait.)
--
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
Tiens, ça fait longtemps que je n'en ai pas parlé. C'est pour ça qu'il existe Fallible<T> ; on renvoie Fallible< std::string >, et le tour est joué. C'est même plus robuste, puisque tout essai à accéder à la chaîne si la variable de contrôle est fausse donne une violation d'une assertion.
Ca a l'air intéressant J'ai trouvé ce lien: http://cpptips.hyperformix.com/cpptips/fallible y'aurait-t il mieux ?
Il y avait une implémentation complète dans ma bibliothèque, mais pour des raisons diverses, elle n'est pas en ligne actuellement. Sinon, je crois que le concepte est assez simple, et il y a même une implémentation dans la page que tu cites.
La seule chose à ajouter, réelement, c'est que depuis, j'ai ajouté une fonction membre :
template< typename T > T Fallible< T >::elseDefaultTo( T const& defaultValue ) { return isValid() ? value : defaultValue ; }
Aussi, une ou deux fois il m'est arrivé d'avoir besoin de plus d'informations dans le cas d'erreur. Alors, j'ai réécrit mon propre « fallible » à la main, plutôt que d'utiliser le template, avec une enum à la place du booléen, etc. Je n'y avais pas reflechi à l'époque, mais j'imagine qu'on pourrait faire la même chose de façon générique, avec des traits. Quelque chose du genre :
// --------------------------------------------------------------------------- // Contraints : // // Sur Value : // Supporte la copie, l'affectation, et la construction par // défaut. // // L'affectation d'une Value doit donner la garantie forte // par rapport aux exceptions. // // Sur Traits : // Définit tous les éléments définis dans // DefaultFallibleTraits. // // Sur Traits::StatusType : // Supporte la copie et l'affectation, sans risque // d'exception. // // Value et Traits::StatusType ne doivent pas être le même // type. // --------------------------------------------------------------------------- template< typename Value, typename Traits = DefaultFallibleTraits > class Fallible { typedef Traits::StatusType StatusType ;
public: explicit Fallible( StatusType validator = Traits::defaultInvalid() ) ; explicit Fallible( T const& value, StatusType validator = Traits::defaultValid() ) ; Fallible& operator=( T const& value ) ; Fallible& operator=( StatusType validator ) ; // Constructeur de copie, affectation par copie et // destructeur fournis par le compilateur...
bool isValid() const ; StatusType status() const ; T const& value() const ; T elseDefaultTo( T const& defaultValue ) const ;
private: // Attention : // L'ordre des déclarations ici est critique pour la // bonne gestion des exceptions. Lors d'une affectation, // il faut toujours que myValue soit affectée avant // myStatus ; sinon, si l'affectation de myValue lève une // exception, on risque d'avoir un état valid sans avoir // de valeur valide. (L'ordre des déclarations détermine // l'ordre des affectations dans l'opérateur // d'affectation générée par le compilateur.) // ----------------------------------------------------------------------- T myValue ; StatusType myStatus ; } ;
(Attention : je viens juste d'avoir l'idée ; le code ci-dessus n'est qu'une première esquisse, écrit dans une démi-heure, et jamais compilé. Il y a donc de fortes chances qu'il contient des erreurs. Mais ça doit donner une idée de ce qu'il faudrait.)
-- 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