Moyennant une petite macro verify() qui permet de connaitre
le fichier & la ligne où on se situe :
#define verify(x) Verify( x, __FILE__, __LINE__ )
Moyennant une petite macro verify() qui permet de connaitre
le fichier & la ligne où on se situe :
#define verify(x) Verify( x, __FILE__, __LINE__ )
Moyennant une petite macro verify() qui permet de connaitre
le fichier & la ligne où on se situe :
#define verify(x) Verify( x, __FILE__, __LINE__ )
Aurélien REGAT-BARREL wrote:Moyennant une petite macro verify() qui permet de connaitre
le fichier & la ligne où on se situe :
#define verify(x) Verify( x, __FILE__, __LINE__ )
Je croyais que tu étais opposé à une solution à base de macro ?
Aurélien REGAT-BARREL wrote:
Moyennant une petite macro verify() qui permet de connaitre
le fichier & la ligne où on se situe :
#define verify(x) Verify( x, __FILE__, __LINE__ )
Je croyais que tu étais opposé à une solution à base de macro ?
Aurélien REGAT-BARREL wrote:Moyennant une petite macro verify() qui permet de connaitre
le fichier & la ligne où on se situe :
#define verify(x) Verify( x, __FILE__, __LINE__ )
Je croyais que tu étais opposé à une solution à base de macro ?
#define verify(x) Verify( x, __FILE__, __LINE__ )
Je croyais que tu étais opposé à une solution à base de macro ?
#define verify(x) Verify( x, __FILE__, __LINE__ )
Je croyais que tu étais opposé à une solution à base de macro ?
#define verify(x) Verify( x, __FILE__, __LINE__ )
Je croyais que tu étais opposé à une solution à base de macro ?
Jusque là j'aimerais avoir votre avis.
Mais attention j'ai l'esprit un peu tordu et ça va plus loin. Allons-y pour
l'usine à gaz. Moyennant une petite macro verify() qui permet de connaitre
le fichier & la ligne où on se situe :
#define verify(x) Verify( x, __FILE__, __LINE__ )
on peut imaginer que Verify initialiserait l'objet Verifier afin que ce
dernier localise l'emplacement de l'erreur. Comme assert() en fait. Sauf
que, j'ai parlé d'usine à gaz....
- Imaginons qu'en cas d'échec Verifier construise un code d'erreur qui
permette d'identifier le fichier et la ligne de l'échec.
- Imaginons qu'un stupide logiciel / script d'extraction de commentaires
génère un gros fichier qui contienne tous les commentaires situés sur la
même ligne ou une ligne au dessus d'un appel à verify()
- et imaginons enfin que ce fichier est structuré de manière à facilement
retrouver le commentaire "associé" à ce couple erreur (fichier - ligne)
eh ben dans un tel cas on pourrai obtenir en message d'erreur le commentaire
associé au verify() qui a échoué, et écrire des commentaires ferait partie
de la procédure de gestion des erreurs. Ces commentaires servent aussi à
documenter le projet...
Et on peut imaginer que le fichier résultat puisse être traduit par la suite
afin d'offrir des messages d'erreurs dans la langue que l'on veut.
Que pensez-vous de cette approche ?
Jusque là j'aimerais avoir votre avis.
Mais attention j'ai l'esprit un peu tordu et ça va plus loin. Allons-y pour
l'usine à gaz. Moyennant une petite macro verify() qui permet de connaitre
le fichier & la ligne où on se situe :
#define verify(x) Verify( x, __FILE__, __LINE__ )
on peut imaginer que Verify initialiserait l'objet Verifier afin que ce
dernier localise l'emplacement de l'erreur. Comme assert() en fait. Sauf
que, j'ai parlé d'usine à gaz....
- Imaginons qu'en cas d'échec Verifier construise un code d'erreur qui
permette d'identifier le fichier et la ligne de l'échec.
- Imaginons qu'un stupide logiciel / script d'extraction de commentaires
génère un gros fichier qui contienne tous les commentaires situés sur la
même ligne ou une ligne au dessus d'un appel à verify()
- et imaginons enfin que ce fichier est structuré de manière à facilement
retrouver le commentaire "associé" à ce couple erreur (fichier - ligne)
eh ben dans un tel cas on pourrai obtenir en message d'erreur le commentaire
associé au verify() qui a échoué, et écrire des commentaires ferait partie
de la procédure de gestion des erreurs. Ces commentaires servent aussi à
documenter le projet...
Et on peut imaginer que le fichier résultat puisse être traduit par la suite
afin d'offrir des messages d'erreurs dans la langue que l'on veut.
Que pensez-vous de cette approche ?
Jusque là j'aimerais avoir votre avis.
Mais attention j'ai l'esprit un peu tordu et ça va plus loin. Allons-y pour
l'usine à gaz. Moyennant une petite macro verify() qui permet de connaitre
le fichier & la ligne où on se situe :
#define verify(x) Verify( x, __FILE__, __LINE__ )
on peut imaginer que Verify initialiserait l'objet Verifier afin que ce
dernier localise l'emplacement de l'erreur. Comme assert() en fait. Sauf
que, j'ai parlé d'usine à gaz....
- Imaginons qu'en cas d'échec Verifier construise un code d'erreur qui
permette d'identifier le fichier et la ligne de l'échec.
- Imaginons qu'un stupide logiciel / script d'extraction de commentaires
génère un gros fichier qui contienne tous les commentaires situés sur la
même ligne ou une ligne au dessus d'un appel à verify()
- et imaginons enfin que ce fichier est structuré de manière à facilement
retrouver le commentaire "associé" à ce couple erreur (fichier - ligne)
eh ben dans un tel cas on pourrai obtenir en message d'erreur le commentaire
associé au verify() qui a échoué, et écrire des commentaires ferait partie
de la procédure de gestion des erreurs. Ces commentaires servent aussi à
documenter le projet...
Et on peut imaginer que le fichier résultat puisse être traduit par la suite
afin d'offrir des messages d'erreurs dans la langue que l'on veut.
Que pensez-vous de cette approche ?
Bonjour à tous,
Si vous avez lu le thread "[TORDU] Exception dans un destructeur, oui
mais..." vous savez que je suis en train de réfléchir à une meilleur
gestion
des erreurs dans mon programme. Le critère numéro un est la simplicité
d'utilisation, pour encourager le programmeur à l"utiliser.
Le but est de simplifier au maximum un tel bloc de vérification:
int value = ...;
if ( value >= 10 )
{
std::ostringstream oss;
oss << "La valeur n'est pas un chiffre : " << value;
throw std::runtime_error( oss.str() );
}
j'étais parti dans un truc de ce genre:
verify( value < 10 ) << "La valeur n'est pas un chiffre : " << value;
Mais l'implémentation n'est pas top (exception lancée dans un
destructeur),
et finalement je trouve ça moyennement explicite.
Après réflexion, je me suis dit que ce qui était le plus important en fin
de
compte c'était de garder une trace des valeurs erronées. Le reste, à
partir
du moment où on a l'emplacement dans le fichier on retrouve tout.
Alors voici ma nouvelle idée:
// la valeur doit être un chiffre
verify( value ) < 10;
verify() construit et renvoie un Verifier et c'est l'opérateur == de ce
dernier qui fait le test et lève ou non l'exception.
template <typename T>
class Verifier
{
public:
Verifier( const T & p1 ) : p1_( p1 ) {}
void operator == ( const T & p2 )
{
if ( ! ( this->p1_ == p2 ) )
{
std::ostringstream oss;
oss << "Verification failed with "
<< this->p1_ << " == " << p2;
throw std::runtime_error( oss.str() );
}
}
private:
T p1_;
};
template<typename T>
Verifier<T> verify( const T & t )
{
return Verifier<T>( t );
}
Je sais que boost a un truc pour simplifier la déclaration des opérateurs.
Ne connaissant pas la bête, je me suis contenté d'une macro pour
simplifier
la tâche:
template <typename T>
class Verifier
{
public:
Verifier( const T & p1 ) : p1_( p1 ) {}
#define OPERATOR(op)
void operator op ( const T & p2 )
{
if ( ! ( this->p1_ op p2 ) )
{
std::ostringstream oss;
oss << "Verification failed with "
<< this->p1_ << " " #op " " << p2;
throw std::runtime_error( oss.str() );
}
}
OPERATOR( == )
OPERATOR( < )
OPERATOR( > )
OPERATOR( != )
OPERATOR( >= )
OPERATOR( <= )
#undef OPERATOR
private:
T p1_;
};
les opérateurs renvoient void, c'est pas innocent c'est pour empêcher de
les
utiliser dans un autre contexte, je sais pas trop ce que ça ferait.
Jusque là j'aimerais avoir votre avis.
Mais attention j'ai l'esprit un peu tordu et ça va plus loin. Allons-y
pour
l'usine à gaz. Moyennant une petite macro verify() qui permet de connaitre
le fichier & la ligne où on se situe :
#define verify(x) Verify( x, __FILE__, __LINE__ )
on peut imaginer que Verify initialiserait l'objet Verifier afin que ce
dernier localise l'emplacement de l'erreur. Comme assert() en fait. Sauf
que, j'ai parlé d'usine à gaz....
- Imaginons qu'en cas d'échec Verifier construise un code d'erreur qui
permette d'identifier le fichier et la ligne de l'échec.
- Imaginons qu'un stupide logiciel / script d'extraction de commentaires
génère un gros fichier qui contienne tous les commentaires situés sur la
même ligne ou une ligne au dessus d'un appel à verify()
- et imaginons enfin que ce fichier est structuré de manière à facilement
retrouver le commentaire "associé" à ce couple erreur (fichier - ligne)
eh ben dans un tel cas on pourrai obtenir en message d'erreur le
commentaire
associé au verify() qui a échoué, et écrire des commentaires ferait partie
de la procédure de gestion des erreurs. Ces commentaires servent aussi à
documenter le projet...
Et on peut imaginer que le fichier résultat puisse être traduit par la
suite
afin d'offrir des messages d'erreurs dans la langue que l'on veut.
Que pensez-vous de cette approche ?
--
Aurélien REGAT-BARREL
Bonjour à tous,
Si vous avez lu le thread "[TORDU] Exception dans un destructeur, oui
mais..." vous savez que je suis en train de réfléchir à une meilleur
gestion
des erreurs dans mon programme. Le critère numéro un est la simplicité
d'utilisation, pour encourager le programmeur à l"utiliser.
Le but est de simplifier au maximum un tel bloc de vérification:
int value = ...;
if ( value >= 10 )
{
std::ostringstream oss;
oss << "La valeur n'est pas un chiffre : " << value;
throw std::runtime_error( oss.str() );
}
j'étais parti dans un truc de ce genre:
verify( value < 10 ) << "La valeur n'est pas un chiffre : " << value;
Mais l'implémentation n'est pas top (exception lancée dans un
destructeur),
et finalement je trouve ça moyennement explicite.
Après réflexion, je me suis dit que ce qui était le plus important en fin
de
compte c'était de garder une trace des valeurs erronées. Le reste, à
partir
du moment où on a l'emplacement dans le fichier on retrouve tout.
Alors voici ma nouvelle idée:
// la valeur doit être un chiffre
verify( value ) < 10;
verify() construit et renvoie un Verifier et c'est l'opérateur == de ce
dernier qui fait le test et lève ou non l'exception.
template <typename T>
class Verifier
{
public:
Verifier( const T & p1 ) : p1_( p1 ) {}
void operator == ( const T & p2 )
{
if ( ! ( this->p1_ == p2 ) )
{
std::ostringstream oss;
oss << "Verification failed with "
<< this->p1_ << " == " << p2;
throw std::runtime_error( oss.str() );
}
}
private:
T p1_;
};
template<typename T>
Verifier<T> verify( const T & t )
{
return Verifier<T>( t );
}
Je sais que boost a un truc pour simplifier la déclaration des opérateurs.
Ne connaissant pas la bête, je me suis contenté d'une macro pour
simplifier
la tâche:
template <typename T>
class Verifier
{
public:
Verifier( const T & p1 ) : p1_( p1 ) {}
#define OPERATOR(op)
void operator op ( const T & p2 )
{
if ( ! ( this->p1_ op p2 ) )
{
std::ostringstream oss;
oss << "Verification failed with "
<< this->p1_ << " " #op " " << p2;
throw std::runtime_error( oss.str() );
}
}
OPERATOR( == )
OPERATOR( < )
OPERATOR( > )
OPERATOR( != )
OPERATOR( >= )
OPERATOR( <= )
#undef OPERATOR
private:
T p1_;
};
les opérateurs renvoient void, c'est pas innocent c'est pour empêcher de
les
utiliser dans un autre contexte, je sais pas trop ce que ça ferait.
Jusque là j'aimerais avoir votre avis.
Mais attention j'ai l'esprit un peu tordu et ça va plus loin. Allons-y
pour
l'usine à gaz. Moyennant une petite macro verify() qui permet de connaitre
le fichier & la ligne où on se situe :
#define verify(x) Verify( x, __FILE__, __LINE__ )
on peut imaginer que Verify initialiserait l'objet Verifier afin que ce
dernier localise l'emplacement de l'erreur. Comme assert() en fait. Sauf
que, j'ai parlé d'usine à gaz....
- Imaginons qu'en cas d'échec Verifier construise un code d'erreur qui
permette d'identifier le fichier et la ligne de l'échec.
- Imaginons qu'un stupide logiciel / script d'extraction de commentaires
génère un gros fichier qui contienne tous les commentaires situés sur la
même ligne ou une ligne au dessus d'un appel à verify()
- et imaginons enfin que ce fichier est structuré de manière à facilement
retrouver le commentaire "associé" à ce couple erreur (fichier - ligne)
eh ben dans un tel cas on pourrai obtenir en message d'erreur le
commentaire
associé au verify() qui a échoué, et écrire des commentaires ferait partie
de la procédure de gestion des erreurs. Ces commentaires servent aussi à
documenter le projet...
Et on peut imaginer que le fichier résultat puisse être traduit par la
suite
afin d'offrir des messages d'erreurs dans la langue que l'on veut.
Que pensez-vous de cette approche ?
--
Aurélien REGAT-BARREL
Bonjour à tous,
Si vous avez lu le thread "[TORDU] Exception dans un destructeur, oui
mais..." vous savez que je suis en train de réfléchir à une meilleur
gestion
des erreurs dans mon programme. Le critère numéro un est la simplicité
d'utilisation, pour encourager le programmeur à l"utiliser.
Le but est de simplifier au maximum un tel bloc de vérification:
int value = ...;
if ( value >= 10 )
{
std::ostringstream oss;
oss << "La valeur n'est pas un chiffre : " << value;
throw std::runtime_error( oss.str() );
}
j'étais parti dans un truc de ce genre:
verify( value < 10 ) << "La valeur n'est pas un chiffre : " << value;
Mais l'implémentation n'est pas top (exception lancée dans un
destructeur),
et finalement je trouve ça moyennement explicite.
Après réflexion, je me suis dit que ce qui était le plus important en fin
de
compte c'était de garder une trace des valeurs erronées. Le reste, à
partir
du moment où on a l'emplacement dans le fichier on retrouve tout.
Alors voici ma nouvelle idée:
// la valeur doit être un chiffre
verify( value ) < 10;
verify() construit et renvoie un Verifier et c'est l'opérateur == de ce
dernier qui fait le test et lève ou non l'exception.
template <typename T>
class Verifier
{
public:
Verifier( const T & p1 ) : p1_( p1 ) {}
void operator == ( const T & p2 )
{
if ( ! ( this->p1_ == p2 ) )
{
std::ostringstream oss;
oss << "Verification failed with "
<< this->p1_ << " == " << p2;
throw std::runtime_error( oss.str() );
}
}
private:
T p1_;
};
template<typename T>
Verifier<T> verify( const T & t )
{
return Verifier<T>( t );
}
Je sais que boost a un truc pour simplifier la déclaration des opérateurs.
Ne connaissant pas la bête, je me suis contenté d'une macro pour
simplifier
la tâche:
template <typename T>
class Verifier
{
public:
Verifier( const T & p1 ) : p1_( p1 ) {}
#define OPERATOR(op)
void operator op ( const T & p2 )
{
if ( ! ( this->p1_ op p2 ) )
{
std::ostringstream oss;
oss << "Verification failed with "
<< this->p1_ << " " #op " " << p2;
throw std::runtime_error( oss.str() );
}
}
OPERATOR( == )
OPERATOR( < )
OPERATOR( > )
OPERATOR( != )
OPERATOR( >= )
OPERATOR( <= )
#undef OPERATOR
private:
T p1_;
};
les opérateurs renvoient void, c'est pas innocent c'est pour empêcher de
les
utiliser dans un autre contexte, je sais pas trop ce que ça ferait.
Jusque là j'aimerais avoir votre avis.
Mais attention j'ai l'esprit un peu tordu et ça va plus loin. Allons-y
pour
l'usine à gaz. Moyennant une petite macro verify() qui permet de connaitre
le fichier & la ligne où on se situe :
#define verify(x) Verify( x, __FILE__, __LINE__ )
on peut imaginer que Verify initialiserait l'objet Verifier afin que ce
dernier localise l'emplacement de l'erreur. Comme assert() en fait. Sauf
que, j'ai parlé d'usine à gaz....
- Imaginons qu'en cas d'échec Verifier construise un code d'erreur qui
permette d'identifier le fichier et la ligne de l'échec.
- Imaginons qu'un stupide logiciel / script d'extraction de commentaires
génère un gros fichier qui contienne tous les commentaires situés sur la
même ligne ou une ligne au dessus d'un appel à verify()
- et imaginons enfin que ce fichier est structuré de manière à facilement
retrouver le commentaire "associé" à ce couple erreur (fichier - ligne)
eh ben dans un tel cas on pourrai obtenir en message d'erreur le
commentaire
associé au verify() qui a échoué, et écrire des commentaires ferait partie
de la procédure de gestion des erreurs. Ces commentaires servent aussi à
documenter le projet...
Et on peut imaginer que le fichier résultat puisse être traduit par la
suite
afin d'offrir des messages d'erreurs dans la langue que l'on veut.
Que pensez-vous de cette approche ?
--
Aurélien REGAT-BARREL
Bonjour,
Je préférais de loin ton idée précédente.
verify(version != 1) << "incorrect file version: " << version;
1. Maintenant, du point de vue de l'implementation, on ne peut a priori
pas
lancer d'exception dans un destructeur...
mais par contre on peut ecrire l'esprit tranquile:
preverif( verify(version != 1) << "incorrect file version: " << version );
ici, verify construit un objet avec la condition evaluee et le message
d'erreur.
preverif est une fonction qui si la condition est false throw une
exception.
2. grace aux joies de la precedence des operateurs, on peut transformer
cette expression en:
preverif() | verify(version != 1) << "incorrect file version: " <<
version;
Cette fois, preverif() est un objet qui a une fonction membre operator|.
operator| a une precedence moins eleve que << donc c'est << qui est evalué
en premier.
3. enfin une petite macro:
#define verif(a) preverif() | verify(a)
et on peut écrire:
verify(version != 1) << "incorrect file version: " << version;
voici le source complet:
struct verify
{
bool m_b;
std::ostringstream m_stream;
verify(bool a_b) : m_b(a_b) {}
template<class T> verify& operator<< (T& a_t)
{
m_stream << a_t;
return *this;
}
};
struct preverif
{
void operator| (const verify& a_verif)
{
if (!a_verif.m_b) throw
std::runtime_error(a_verif.m_stream.str());
}
};
#define verif(a) preverif() | verify(a)
SerGioGio
"Aurélien REGAT-BARREL" a écrit dans le
message de news:41eceddd$0$25762$Bonjour à tous,
Si vous avez lu le thread "[TORDU] Exception dans un destructeur, oui
mais..." vous savez que je suis en train de réfléchir à une meilleur
gestiondes erreurs dans mon programme. Le critère numéro un est la simplicité
d'utilisation, pour encourager le programmeur à l"utiliser.
Le but est de simplifier au maximum un tel bloc de vérification:
int value = ...;
if ( value >= 10 )
{
std::ostringstream oss;
oss << "La valeur n'est pas un chiffre : " << value;
throw std::runtime_error( oss.str() );
}
j'étais parti dans un truc de ce genre:
verify( value < 10 ) << "La valeur n'est pas un chiffre : " << value;
Mais l'implémentation n'est pas top (exception lancée dans un
destructeur),et finalement je trouve ça moyennement explicite.
Après réflexion, je me suis dit que ce qui était le plus important en
fin
decompte c'était de garder une trace des valeurs erronées. Le reste, à
partirdu moment où on a l'emplacement dans le fichier on retrouve tout.
Alors voici ma nouvelle idée:
// la valeur doit être un chiffre
verify( value ) < 10;
verify() construit et renvoie un Verifier et c'est l'opérateur == de ce
dernier qui fait le test et lève ou non l'exception.
template <typename T>
class Verifier
{
public:
Verifier( const T & p1 ) : p1_( p1 ) {}
void operator == ( const T & p2 )
{
if ( ! ( this->p1_ == p2 ) )
{
std::ostringstream oss;
oss << "Verification failed with "
<< this->p1_ << " == " << p2;
throw std::runtime_error( oss.str() );
}
}
private:
T p1_;
};
template<typename T>
Verifier<T> verify( const T & t )
{
return Verifier<T>( t );
}
Je sais que boost a un truc pour simplifier la déclaration des
opérateurs.
Ne connaissant pas la bête, je me suis contenté d'une macro pour
simplifierla tâche:
template <typename T>
class Verifier
{
public:
Verifier( const T & p1 ) : p1_( p1 ) {}
#define OPERATOR(op)
void operator op ( const T & p2 )
{
if ( ! ( this->p1_ op p2 ) )
{
std::ostringstream oss;
oss << "Verification failed with "
<< this->p1_ << " " #op " " << p2;
throw std::runtime_error( oss.str() );
}
}
OPERATOR( == )
OPERATOR( < )
OPERATOR( > )
OPERATOR( != )
OPERATOR( >= )
OPERATOR( <= )
#undef OPERATOR
private:
T p1_;
};
les opérateurs renvoient void, c'est pas innocent c'est pour empêcher de
lesutiliser dans un autre contexte, je sais pas trop ce que ça ferait.
Jusque là j'aimerais avoir votre avis.
Mais attention j'ai l'esprit un peu tordu et ça va plus loin. Allons-y
pourl'usine à gaz. Moyennant une petite macro verify() qui permet de
connaitre
le fichier & la ligne où on se situe :
#define verify(x) Verify( x, __FILE__, __LINE__ )
on peut imaginer que Verify initialiserait l'objet Verifier afin que ce
dernier localise l'emplacement de l'erreur. Comme assert() en fait. Sauf
que, j'ai parlé d'usine à gaz....
- Imaginons qu'en cas d'échec Verifier construise un code d'erreur qui
permette d'identifier le fichier et la ligne de l'échec.
- Imaginons qu'un stupide logiciel / script d'extraction de commentaires
génère un gros fichier qui contienne tous les commentaires situés sur la
même ligne ou une ligne au dessus d'un appel à verify()
- et imaginons enfin que ce fichier est structuré de manière à
facilement
retrouver le commentaire "associé" à ce couple erreur (fichier - ligne)
eh ben dans un tel cas on pourrai obtenir en message d'erreur le
commentaireassocié au verify() qui a échoué, et écrire des commentaires ferait
partie
de la procédure de gestion des erreurs. Ces commentaires servent aussi à
documenter le projet...
Et on peut imaginer que le fichier résultat puisse être traduit par la
suiteafin d'offrir des messages d'erreurs dans la langue que l'on veut.
Que pensez-vous de cette approche ?
--
Aurélien REGAT-BARREL
Bonjour,
Je préférais de loin ton idée précédente.
verify(version != 1) << "incorrect file version: " << version;
1. Maintenant, du point de vue de l'implementation, on ne peut a priori
pas
lancer d'exception dans un destructeur...
mais par contre on peut ecrire l'esprit tranquile:
preverif( verify(version != 1) << "incorrect file version: " << version );
ici, verify construit un objet avec la condition evaluee et le message
d'erreur.
preverif est une fonction qui si la condition est false throw une
exception.
2. grace aux joies de la precedence des operateurs, on peut transformer
cette expression en:
preverif() | verify(version != 1) << "incorrect file version: " <<
version;
Cette fois, preverif() est un objet qui a une fonction membre operator|.
operator| a une precedence moins eleve que << donc c'est << qui est evalué
en premier.
3. enfin une petite macro:
#define verif(a) preverif() | verify(a)
et on peut écrire:
verify(version != 1) << "incorrect file version: " << version;
voici le source complet:
struct verify
{
bool m_b;
std::ostringstream m_stream;
verify(bool a_b) : m_b(a_b) {}
template<class T> verify& operator<< (T& a_t)
{
m_stream << a_t;
return *this;
}
};
struct preverif
{
void operator| (const verify& a_verif)
{
if (!a_verif.m_b) throw
std::runtime_error(a_verif.m_stream.str());
}
};
#define verif(a) preverif() | verify(a)
SerGioGio
"Aurélien REGAT-BARREL" <nospam-aregatba@yahoo.fr.invalid> a écrit dans le
message de news:41eceddd$0$25762$626a14ce@news.free.fr...
Bonjour à tous,
Si vous avez lu le thread "[TORDU] Exception dans un destructeur, oui
mais..." vous savez que je suis en train de réfléchir à une meilleur
gestion
des erreurs dans mon programme. Le critère numéro un est la simplicité
d'utilisation, pour encourager le programmeur à l"utiliser.
Le but est de simplifier au maximum un tel bloc de vérification:
int value = ...;
if ( value >= 10 )
{
std::ostringstream oss;
oss << "La valeur n'est pas un chiffre : " << value;
throw std::runtime_error( oss.str() );
}
j'étais parti dans un truc de ce genre:
verify( value < 10 ) << "La valeur n'est pas un chiffre : " << value;
Mais l'implémentation n'est pas top (exception lancée dans un
destructeur),
et finalement je trouve ça moyennement explicite.
Après réflexion, je me suis dit que ce qui était le plus important en
fin
de
compte c'était de garder une trace des valeurs erronées. Le reste, à
partir
du moment où on a l'emplacement dans le fichier on retrouve tout.
Alors voici ma nouvelle idée:
// la valeur doit être un chiffre
verify( value ) < 10;
verify() construit et renvoie un Verifier et c'est l'opérateur == de ce
dernier qui fait le test et lève ou non l'exception.
template <typename T>
class Verifier
{
public:
Verifier( const T & p1 ) : p1_( p1 ) {}
void operator == ( const T & p2 )
{
if ( ! ( this->p1_ == p2 ) )
{
std::ostringstream oss;
oss << "Verification failed with "
<< this->p1_ << " == " << p2;
throw std::runtime_error( oss.str() );
}
}
private:
T p1_;
};
template<typename T>
Verifier<T> verify( const T & t )
{
return Verifier<T>( t );
}
Je sais que boost a un truc pour simplifier la déclaration des
opérateurs.
Ne connaissant pas la bête, je me suis contenté d'une macro pour
simplifier
la tâche:
template <typename T>
class Verifier
{
public:
Verifier( const T & p1 ) : p1_( p1 ) {}
#define OPERATOR(op)
void operator op ( const T & p2 )
{
if ( ! ( this->p1_ op p2 ) )
{
std::ostringstream oss;
oss << "Verification failed with "
<< this->p1_ << " " #op " " << p2;
throw std::runtime_error( oss.str() );
}
}
OPERATOR( == )
OPERATOR( < )
OPERATOR( > )
OPERATOR( != )
OPERATOR( >= )
OPERATOR( <= )
#undef OPERATOR
private:
T p1_;
};
les opérateurs renvoient void, c'est pas innocent c'est pour empêcher de
les
utiliser dans un autre contexte, je sais pas trop ce que ça ferait.
Jusque là j'aimerais avoir votre avis.
Mais attention j'ai l'esprit un peu tordu et ça va plus loin. Allons-y
pour
l'usine à gaz. Moyennant une petite macro verify() qui permet de
connaitre
le fichier & la ligne où on se situe :
#define verify(x) Verify( x, __FILE__, __LINE__ )
on peut imaginer que Verify initialiserait l'objet Verifier afin que ce
dernier localise l'emplacement de l'erreur. Comme assert() en fait. Sauf
que, j'ai parlé d'usine à gaz....
- Imaginons qu'en cas d'échec Verifier construise un code d'erreur qui
permette d'identifier le fichier et la ligne de l'échec.
- Imaginons qu'un stupide logiciel / script d'extraction de commentaires
génère un gros fichier qui contienne tous les commentaires situés sur la
même ligne ou une ligne au dessus d'un appel à verify()
- et imaginons enfin que ce fichier est structuré de manière à
facilement
retrouver le commentaire "associé" à ce couple erreur (fichier - ligne)
eh ben dans un tel cas on pourrai obtenir en message d'erreur le
commentaire
associé au verify() qui a échoué, et écrire des commentaires ferait
partie
de la procédure de gestion des erreurs. Ces commentaires servent aussi à
documenter le projet...
Et on peut imaginer que le fichier résultat puisse être traduit par la
suite
afin d'offrir des messages d'erreurs dans la langue que l'on veut.
Que pensez-vous de cette approche ?
--
Aurélien REGAT-BARREL
Bonjour,
Je préférais de loin ton idée précédente.
verify(version != 1) << "incorrect file version: " << version;
1. Maintenant, du point de vue de l'implementation, on ne peut a priori
pas
lancer d'exception dans un destructeur...
mais par contre on peut ecrire l'esprit tranquile:
preverif( verify(version != 1) << "incorrect file version: " << version );
ici, verify construit un objet avec la condition evaluee et le message
d'erreur.
preverif est une fonction qui si la condition est false throw une
exception.
2. grace aux joies de la precedence des operateurs, on peut transformer
cette expression en:
preverif() | verify(version != 1) << "incorrect file version: " <<
version;
Cette fois, preverif() est un objet qui a une fonction membre operator|.
operator| a une precedence moins eleve que << donc c'est << qui est evalué
en premier.
3. enfin une petite macro:
#define verif(a) preverif() | verify(a)
et on peut écrire:
verify(version != 1) << "incorrect file version: " << version;
voici le source complet:
struct verify
{
bool m_b;
std::ostringstream m_stream;
verify(bool a_b) : m_b(a_b) {}
template<class T> verify& operator<< (T& a_t)
{
m_stream << a_t;
return *this;
}
};
struct preverif
{
void operator| (const verify& a_verif)
{
if (!a_verif.m_b) throw
std::runtime_error(a_verif.m_stream.str());
}
};
#define verif(a) preverif() | verify(a)
SerGioGio
"Aurélien REGAT-BARREL" a écrit dans le
message de news:41eceddd$0$25762$Bonjour à tous,
Si vous avez lu le thread "[TORDU] Exception dans un destructeur, oui
mais..." vous savez que je suis en train de réfléchir à une meilleur
gestiondes erreurs dans mon programme. Le critère numéro un est la simplicité
d'utilisation, pour encourager le programmeur à l"utiliser.
Le but est de simplifier au maximum un tel bloc de vérification:
int value = ...;
if ( value >= 10 )
{
std::ostringstream oss;
oss << "La valeur n'est pas un chiffre : " << value;
throw std::runtime_error( oss.str() );
}
j'étais parti dans un truc de ce genre:
verify( value < 10 ) << "La valeur n'est pas un chiffre : " << value;
Mais l'implémentation n'est pas top (exception lancée dans un
destructeur),et finalement je trouve ça moyennement explicite.
Après réflexion, je me suis dit que ce qui était le plus important en
fin
decompte c'était de garder une trace des valeurs erronées. Le reste, à
partirdu moment où on a l'emplacement dans le fichier on retrouve tout.
Alors voici ma nouvelle idée:
// la valeur doit être un chiffre
verify( value ) < 10;
verify() construit et renvoie un Verifier et c'est l'opérateur == de ce
dernier qui fait le test et lève ou non l'exception.
template <typename T>
class Verifier
{
public:
Verifier( const T & p1 ) : p1_( p1 ) {}
void operator == ( const T & p2 )
{
if ( ! ( this->p1_ == p2 ) )
{
std::ostringstream oss;
oss << "Verification failed with "
<< this->p1_ << " == " << p2;
throw std::runtime_error( oss.str() );
}
}
private:
T p1_;
};
template<typename T>
Verifier<T> verify( const T & t )
{
return Verifier<T>( t );
}
Je sais que boost a un truc pour simplifier la déclaration des
opérateurs.
Ne connaissant pas la bête, je me suis contenté d'une macro pour
simplifierla tâche:
template <typename T>
class Verifier
{
public:
Verifier( const T & p1 ) : p1_( p1 ) {}
#define OPERATOR(op)
void operator op ( const T & p2 )
{
if ( ! ( this->p1_ op p2 ) )
{
std::ostringstream oss;
oss << "Verification failed with "
<< this->p1_ << " " #op " " << p2;
throw std::runtime_error( oss.str() );
}
}
OPERATOR( == )
OPERATOR( < )
OPERATOR( > )
OPERATOR( != )
OPERATOR( >= )
OPERATOR( <= )
#undef OPERATOR
private:
T p1_;
};
les opérateurs renvoient void, c'est pas innocent c'est pour empêcher de
lesutiliser dans un autre contexte, je sais pas trop ce que ça ferait.
Jusque là j'aimerais avoir votre avis.
Mais attention j'ai l'esprit un peu tordu et ça va plus loin. Allons-y
pourl'usine à gaz. Moyennant une petite macro verify() qui permet de
connaitre
le fichier & la ligne où on se situe :
#define verify(x) Verify( x, __FILE__, __LINE__ )
on peut imaginer que Verify initialiserait l'objet Verifier afin que ce
dernier localise l'emplacement de l'erreur. Comme assert() en fait. Sauf
que, j'ai parlé d'usine à gaz....
- Imaginons qu'en cas d'échec Verifier construise un code d'erreur qui
permette d'identifier le fichier et la ligne de l'échec.
- Imaginons qu'un stupide logiciel / script d'extraction de commentaires
génère un gros fichier qui contienne tous les commentaires situés sur la
même ligne ou une ligne au dessus d'un appel à verify()
- et imaginons enfin que ce fichier est structuré de manière à
facilement
retrouver le commentaire "associé" à ce couple erreur (fichier - ligne)
eh ben dans un tel cas on pourrai obtenir en message d'erreur le
commentaireassocié au verify() qui a échoué, et écrire des commentaires ferait
partie
de la procédure de gestion des erreurs. Ces commentaires servent aussi à
documenter le projet...
Et on peut imaginer que le fichier résultat puisse être traduit par la
suiteafin d'offrir des messages d'erreurs dans la langue que l'on veut.
Que pensez-vous de cette approche ?
--
Aurélien REGAT-BARREL
Il y a toujours plus simple, et moins problématique, en utilisant
stringstream.
struct verify
{
bool m_b;
verify(bool a_b) : m_b(a_b) { }
void operator| (const std::ostream& a_stream)
{
std::istreambuf_iterator<char> beg(a_stream.rdbuf());
std::istreambuf_iterator<char> end;
if (!m_b) throw std::runtime_error(std::string(beg, end));
}
};
#define verif(a) verify(a) | std::stringstream() << std::flush << __FILE__
<< "(" << __LINE__ << ") "
L'appel à flush est nécéssaire, car par exemple, aussi surprenant que ça
puisse paraitre,
std::stringstream() << "hello world" appelle la fonction membre operator<<
(void* ) au lieu de la fonction globale operator<<(std::ostream&, const
char*) comme on aurait pu s'y attendre.
D'après ce que j'ai compris, la raison est que on ne peut pas lier un
object
temporaire à une référence non-const, or std::stringstream() est un
temporaire, std::ostream& est une référence non-const, donc la fonction
globale operator<<(std::ostream&, const char*) est disqualifiée...
Par contre, on peut toujours appeler une fonction membre d'un temporaire,
et
cette fonction membre est autorisée à renvoyer une référence non-const sur
l'objet, d'où le flush...
Donc la macro est au minimum:
#define verif(a) verify(a) | std::stringstream() << std::flush
Il y a toujours plus simple, et moins problématique, en utilisant
stringstream.
struct verify
{
bool m_b;
verify(bool a_b) : m_b(a_b) { }
void operator| (const std::ostream& a_stream)
{
std::istreambuf_iterator<char> beg(a_stream.rdbuf());
std::istreambuf_iterator<char> end;
if (!m_b) throw std::runtime_error(std::string(beg, end));
}
};
#define verif(a) verify(a) | std::stringstream() << std::flush << __FILE__
<< "(" << __LINE__ << ") "
L'appel à flush est nécéssaire, car par exemple, aussi surprenant que ça
puisse paraitre,
std::stringstream() << "hello world" appelle la fonction membre operator<<
(void* ) au lieu de la fonction globale operator<<(std::ostream&, const
char*) comme on aurait pu s'y attendre.
D'après ce que j'ai compris, la raison est que on ne peut pas lier un
object
temporaire à une référence non-const, or std::stringstream() est un
temporaire, std::ostream& est une référence non-const, donc la fonction
globale operator<<(std::ostream&, const char*) est disqualifiée...
Par contre, on peut toujours appeler une fonction membre d'un temporaire,
et
cette fonction membre est autorisée à renvoyer une référence non-const sur
l'objet, d'où le flush...
Donc la macro est au minimum:
#define verif(a) verify(a) | std::stringstream() << std::flush
Il y a toujours plus simple, et moins problématique, en utilisant
stringstream.
struct verify
{
bool m_b;
verify(bool a_b) : m_b(a_b) { }
void operator| (const std::ostream& a_stream)
{
std::istreambuf_iterator<char> beg(a_stream.rdbuf());
std::istreambuf_iterator<char> end;
if (!m_b) throw std::runtime_error(std::string(beg, end));
}
};
#define verif(a) verify(a) | std::stringstream() << std::flush << __FILE__
<< "(" << __LINE__ << ") "
L'appel à flush est nécéssaire, car par exemple, aussi surprenant que ça
puisse paraitre,
std::stringstream() << "hello world" appelle la fonction membre operator<<
(void* ) au lieu de la fonction globale operator<<(std::ostream&, const
char*) comme on aurait pu s'y attendre.
D'après ce que j'ai compris, la raison est que on ne peut pas lier un
object
temporaire à une référence non-const, or std::stringstream() est un
temporaire, std::ostream& est une référence non-const, donc la fonction
globale operator<<(std::ostream&, const char*) est disqualifiée...
Par contre, on peut toujours appeler une fonction membre d'un temporaire,
et
cette fonction membre est autorisée à renvoyer une référence non-const sur
l'objet, d'où le flush...
Donc la macro est au minimum:
#define verif(a) verify(a) | std::stringstream() << std::flush
Bonjour à tous,
Si vous avez lu le thread "[TORDU] Exception dans un destructeur, oui
mais..." vous savez que je suis en train de réfléchir à une meilleur
gestion
des erreurs dans mon programme. Le critère numéro un est la simplicité
d'utilisation, pour encourager le programmeur à l"utiliser.
Le but est de simplifier au maximum un tel bloc de vérification:
int value = ...;
if ( value >= 10 )
{
std::ostringstream oss;
oss << "La valeur n'est pas un chiffre : " << value;
throw std::runtime_error( oss.str() );
}
j'étais parti dans un truc de ce genre:
verify( value < 10 ) << "La valeur n'est pas un chiffre : " << value;
Mais l'implémentation n'est pas top (exception lancée dans un
destructeur),
et finalement je trouve ça moyennement explicite.
Après réflexion, je me suis dit que ce qui était le plus important en fin
de
compte c'était de garder une trace des valeurs erronées. Le reste, à
partir
du moment où on a l'emplacement dans le fichier on retrouve tout.
Alors voici ma nouvelle idée:
// la valeur doit être un chiffre
verify( value ) < 10;
verify() construit et renvoie un Verifier et c'est l'opérateur == de ce
dernier qui fait le test et lève ou non l'exception.
template <typename T>
class Verifier
{
public:
Verifier( const T & p1 ) : p1_( p1 ) {}
void operator == ( const T & p2 )
{
if ( ! ( this->p1_ == p2 ) )
{
std::ostringstream oss;
oss << "Verification failed with "
<< this->p1_ << " == " << p2;
throw std::runtime_error( oss.str() );
}
}
private:
T p1_;
};
template<typename T>
Verifier<T> verify( const T & t )
{
return Verifier<T>( t );
}
Je sais que boost a un truc pour simplifier la déclaration des opérateurs.
Ne connaissant pas la bête, je me suis contenté d'une macro pour
simplifier
la tâche:
template <typename T>
class Verifier
{
public:
Verifier( const T & p1 ) : p1_( p1 ) {}
#define OPERATOR(op)
void operator op ( const T & p2 )
{
if ( ! ( this->p1_ op p2 ) )
{
std::ostringstream oss;
oss << "Verification failed with "
<< this->p1_ << " " #op " " << p2;
throw std::runtime_error( oss.str() );
}
}
OPERATOR( == )
OPERATOR( < )
OPERATOR( > )
OPERATOR( != )
OPERATOR( >= )
OPERATOR( <= )
#undef OPERATOR
private:
T p1_;
};
les opérateurs renvoient void, c'est pas innocent c'est pour empêcher de
les
utiliser dans un autre contexte, je sais pas trop ce que ça ferait.
Jusque là j'aimerais avoir votre avis.
Mais attention j'ai l'esprit un peu tordu et ça va plus loin. Allons-y
pour
l'usine à gaz. Moyennant une petite macro verify() qui permet de connaitre
le fichier & la ligne où on se situe :
#define verify(x) Verify( x, __FILE__, __LINE__ )
on peut imaginer que Verify initialiserait l'objet Verifier afin que ce
dernier localise l'emplacement de l'erreur. Comme assert() en fait. Sauf
que, j'ai parlé d'usine à gaz....
- Imaginons qu'en cas d'échec Verifier construise un code d'erreur qui
permette d'identifier le fichier et la ligne de l'échec.
- Imaginons qu'un stupide logiciel / script d'extraction de commentaires
génère un gros fichier qui contienne tous les commentaires situés sur la
même ligne ou une ligne au dessus d'un appel à verify()
- et imaginons enfin que ce fichier est structuré de manière à facilement
retrouver le commentaire "associé" à ce couple erreur (fichier - ligne)
eh ben dans un tel cas on pourrai obtenir en message d'erreur le
commentaire
associé au verify() qui a échoué, et écrire des commentaires ferait partie
de la procédure de gestion des erreurs. Ces commentaires servent aussi à
documenter le projet...
Et on peut imaginer que le fichier résultat puisse être traduit par la
suite
afin d'offrir des messages d'erreurs dans la langue que l'on veut.
Que pensez-vous de cette approche ?
--
Aurélien REGAT-BARREL
Bonjour à tous,
Si vous avez lu le thread "[TORDU] Exception dans un destructeur, oui
mais..." vous savez que je suis en train de réfléchir à une meilleur
gestion
des erreurs dans mon programme. Le critère numéro un est la simplicité
d'utilisation, pour encourager le programmeur à l"utiliser.
Le but est de simplifier au maximum un tel bloc de vérification:
int value = ...;
if ( value >= 10 )
{
std::ostringstream oss;
oss << "La valeur n'est pas un chiffre : " << value;
throw std::runtime_error( oss.str() );
}
j'étais parti dans un truc de ce genre:
verify( value < 10 ) << "La valeur n'est pas un chiffre : " << value;
Mais l'implémentation n'est pas top (exception lancée dans un
destructeur),
et finalement je trouve ça moyennement explicite.
Après réflexion, je me suis dit que ce qui était le plus important en fin
de
compte c'était de garder une trace des valeurs erronées. Le reste, à
partir
du moment où on a l'emplacement dans le fichier on retrouve tout.
Alors voici ma nouvelle idée:
// la valeur doit être un chiffre
verify( value ) < 10;
verify() construit et renvoie un Verifier et c'est l'opérateur == de ce
dernier qui fait le test et lève ou non l'exception.
template <typename T>
class Verifier
{
public:
Verifier( const T & p1 ) : p1_( p1 ) {}
void operator == ( const T & p2 )
{
if ( ! ( this->p1_ == p2 ) )
{
std::ostringstream oss;
oss << "Verification failed with "
<< this->p1_ << " == " << p2;
throw std::runtime_error( oss.str() );
}
}
private:
T p1_;
};
template<typename T>
Verifier<T> verify( const T & t )
{
return Verifier<T>( t );
}
Je sais que boost a un truc pour simplifier la déclaration des opérateurs.
Ne connaissant pas la bête, je me suis contenté d'une macro pour
simplifier
la tâche:
template <typename T>
class Verifier
{
public:
Verifier( const T & p1 ) : p1_( p1 ) {}
#define OPERATOR(op)
void operator op ( const T & p2 )
{
if ( ! ( this->p1_ op p2 ) )
{
std::ostringstream oss;
oss << "Verification failed with "
<< this->p1_ << " " #op " " << p2;
throw std::runtime_error( oss.str() );
}
}
OPERATOR( == )
OPERATOR( < )
OPERATOR( > )
OPERATOR( != )
OPERATOR( >= )
OPERATOR( <= )
#undef OPERATOR
private:
T p1_;
};
les opérateurs renvoient void, c'est pas innocent c'est pour empêcher de
les
utiliser dans un autre contexte, je sais pas trop ce que ça ferait.
Jusque là j'aimerais avoir votre avis.
Mais attention j'ai l'esprit un peu tordu et ça va plus loin. Allons-y
pour
l'usine à gaz. Moyennant une petite macro verify() qui permet de connaitre
le fichier & la ligne où on se situe :
#define verify(x) Verify( x, __FILE__, __LINE__ )
on peut imaginer que Verify initialiserait l'objet Verifier afin que ce
dernier localise l'emplacement de l'erreur. Comme assert() en fait. Sauf
que, j'ai parlé d'usine à gaz....
- Imaginons qu'en cas d'échec Verifier construise un code d'erreur qui
permette d'identifier le fichier et la ligne de l'échec.
- Imaginons qu'un stupide logiciel / script d'extraction de commentaires
génère un gros fichier qui contienne tous les commentaires situés sur la
même ligne ou une ligne au dessus d'un appel à verify()
- et imaginons enfin que ce fichier est structuré de manière à facilement
retrouver le commentaire "associé" à ce couple erreur (fichier - ligne)
eh ben dans un tel cas on pourrai obtenir en message d'erreur le
commentaire
associé au verify() qui a échoué, et écrire des commentaires ferait partie
de la procédure de gestion des erreurs. Ces commentaires servent aussi à
documenter le projet...
Et on peut imaginer que le fichier résultat puisse être traduit par la
suite
afin d'offrir des messages d'erreurs dans la langue que l'on veut.
Que pensez-vous de cette approche ?
--
Aurélien REGAT-BARREL
Bonjour à tous,
Si vous avez lu le thread "[TORDU] Exception dans un destructeur, oui
mais..." vous savez que je suis en train de réfléchir à une meilleur
gestion
des erreurs dans mon programme. Le critère numéro un est la simplicité
d'utilisation, pour encourager le programmeur à l"utiliser.
Le but est de simplifier au maximum un tel bloc de vérification:
int value = ...;
if ( value >= 10 )
{
std::ostringstream oss;
oss << "La valeur n'est pas un chiffre : " << value;
throw std::runtime_error( oss.str() );
}
j'étais parti dans un truc de ce genre:
verify( value < 10 ) << "La valeur n'est pas un chiffre : " << value;
Mais l'implémentation n'est pas top (exception lancée dans un
destructeur),
et finalement je trouve ça moyennement explicite.
Après réflexion, je me suis dit que ce qui était le plus important en fin
de
compte c'était de garder une trace des valeurs erronées. Le reste, à
partir
du moment où on a l'emplacement dans le fichier on retrouve tout.
Alors voici ma nouvelle idée:
// la valeur doit être un chiffre
verify( value ) < 10;
verify() construit et renvoie un Verifier et c'est l'opérateur == de ce
dernier qui fait le test et lève ou non l'exception.
template <typename T>
class Verifier
{
public:
Verifier( const T & p1 ) : p1_( p1 ) {}
void operator == ( const T & p2 )
{
if ( ! ( this->p1_ == p2 ) )
{
std::ostringstream oss;
oss << "Verification failed with "
<< this->p1_ << " == " << p2;
throw std::runtime_error( oss.str() );
}
}
private:
T p1_;
};
template<typename T>
Verifier<T> verify( const T & t )
{
return Verifier<T>( t );
}
Je sais que boost a un truc pour simplifier la déclaration des opérateurs.
Ne connaissant pas la bête, je me suis contenté d'une macro pour
simplifier
la tâche:
template <typename T>
class Verifier
{
public:
Verifier( const T & p1 ) : p1_( p1 ) {}
#define OPERATOR(op)
void operator op ( const T & p2 )
{
if ( ! ( this->p1_ op p2 ) )
{
std::ostringstream oss;
oss << "Verification failed with "
<< this->p1_ << " " #op " " << p2;
throw std::runtime_error( oss.str() );
}
}
OPERATOR( == )
OPERATOR( < )
OPERATOR( > )
OPERATOR( != )
OPERATOR( >= )
OPERATOR( <= )
#undef OPERATOR
private:
T p1_;
};
les opérateurs renvoient void, c'est pas innocent c'est pour empêcher de
les
utiliser dans un autre contexte, je sais pas trop ce que ça ferait.
Jusque là j'aimerais avoir votre avis.
Mais attention j'ai l'esprit un peu tordu et ça va plus loin. Allons-y
pour
l'usine à gaz. Moyennant une petite macro verify() qui permet de connaitre
le fichier & la ligne où on se situe :
#define verify(x) Verify( x, __FILE__, __LINE__ )
on peut imaginer que Verify initialiserait l'objet Verifier afin que ce
dernier localise l'emplacement de l'erreur. Comme assert() en fait. Sauf
que, j'ai parlé d'usine à gaz....
- Imaginons qu'en cas d'échec Verifier construise un code d'erreur qui
permette d'identifier le fichier et la ligne de l'échec.
- Imaginons qu'un stupide logiciel / script d'extraction de commentaires
génère un gros fichier qui contienne tous les commentaires situés sur la
même ligne ou une ligne au dessus d'un appel à verify()
- et imaginons enfin que ce fichier est structuré de manière à facilement
retrouver le commentaire "associé" à ce couple erreur (fichier - ligne)
eh ben dans un tel cas on pourrai obtenir en message d'erreur le
commentaire
associé au verify() qui a échoué, et écrire des commentaires ferait partie
de la procédure de gestion des erreurs. Ces commentaires servent aussi à
documenter le projet...
Et on peut imaginer que le fichier résultat puisse être traduit par la
suite
afin d'offrir des messages d'erreurs dans la langue que l'on veut.
Que pensez-vous de cette approche ?
--
Aurélien REGAT-BARREL
Cette stack était enfin stockée dans une std::string de la classe
dérivée de std::exception.
Et une méthode "const char *where()" venait donc compléter "const char
*what()" pour renvoyer le lieu de l'exception...
Et ça sert à quoi de connaitre l'adresse dans la pile ?
Cette stack était enfin stockée dans une std::string de la classe
dérivée de std::exception.
Et une méthode "const char *where()" venait donc compléter "const char
*what()" pour renvoyer le lieu de l'exception...
Et ça sert à quoi de connaitre l'adresse dans la pile ?
Cette stack était enfin stockée dans une std::string de la classe
dérivée de std::exception.
Et une méthode "const char *where()" venait donc compléter "const char
*what()" pour renvoyer le lieu de l'exception...
Et ça sert à quoi de connaitre l'adresse dans la pile ?