OVH Cloud OVH Cloud

string::clear() vs string::resize( 0 ) vs string::erase( begin(), end() )

12 réponses
Avatar
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() ?

Merci.

--
Aurélien Regat-Barrel

2 réponses

1 2
Avatar
kanze
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 :

class DefaultFallibleTraits
{
public:
typedef bool StatusType ;
static bool isOk( StatusType validator )
{
return validator ;
}
StatusType defaultInvalid()
{
return false ;
}
StatusType defaultValid()
{
return true ;
}
} ;

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

void invalidate( StatusType newStatus
=
Traits::defaultInvalid() ) ;
void validate( T const& newValue,
StatusType newStatus
=
Traits::defaultValid() ) ;

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

template< typename Value, typename Traits >
Fallible< Value, Traits >::Fallible(
StatusType validator )
: myStatus( validator )
{
assert( ! isValid() ) ;
}

template< typename Value, typename Traits >
Fallible< Value, Traits >::Fallible(
T const& value,
StatusType validator )
: myValue( value )
, myStatus( validator )
{
assert( isValid() ) ;
}

template< typename Value, typename Traits >
Fallible< Value, Traits >::operator=(
T const& value )
{
myValue = value ;
myStatus = Traits::defaultValid() ;
return *this ;
}

template< typename Value, typename Traits >
Fallible< Value, Traits >::operator=(
StatusType validator )
{
bool wasOk = isOk() ;
myStatus = validator ;
assert( ! isOk() || wasOK() ) ;
return *this ;
}

template< typename Value, typename Traits >
bool
Fallible< Value, Traits >::isValid() const
{
return Traits::isOk( myStatus ) ;
}

template< typename Value, typename Traits >
StatusType
Fallible< Value, Traits >::validator() const
{
return myStatus ;
}

template< typename Value, typename Traits >
T const&
Fallible< Value, Traits >::value() const
{
assert( isValid() ) ;
return myValue ;
}

template< typename Value, typename Traits >
T
Fallible< Value, Traits >::elseDefaultTo(
T const& defaultValue ) const
{
return isValid() ? myValue : defaultValue ;
}

template< typename Value, typename Traits >
void
Fallible< Value, Traits >::invalidate(
StatusType newStatus )
{
assert( ! Traits::isOk( newStatus ) ) ;
myStatus = newStatus ;
}

template< typename Value, typename Traits >
void
Fallible< Value, Traits >::validate(
T const& newValue,
StatusType newStatus )
{
assert( Traits::isOk( newStatus ) ) ;
myValue = newValue ;
myStatus = newStatus ;
}

(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


Avatar
Aurelien Regat-Barrel
Ok merci, je garde ça sous le coude.

--
Aurélien Regat-Barrel
1 2