2017-05-08 1 views
4

J'écris une bibliothèque et je souhaite renvoyer des codes d'erreur chaque fois qu'une erreur est renvoyée par un système distant. Le problème est que ceux-ci sont identifiés par des chaînes, par exemple, "0A01" et contiennent également un message, et le code d'erreur nécessite un entier comme valeur.Utilisation de std :: error_code avec des valeurs non entières

Quelle est la meilleure façon d'implémenter un code d'erreur, avec toutes les fonctionnalités fournies par std::error_code mais utilisant des chaînes comme valeur? Comment ajouter une chaîne d'erreur externe au std::error_code ou au std::error_category?

+1

Exceptions? --- – Quentin

+0

J'aimerais utiliser error_codes. Convient mieux avec le flux de l'application. – ruipacheco

+0

S'il existe un nombre fixe de ces codes de chaîne, vous pouvez les mapper en valeurs entières (d'autant qu'elles ressemblent à des valeurs hexadécimales) et utiliser de toute façon 'std :: error_code'. Autrement écrire une classe avec deux champs de chaîne ne devrait pas être difficile du tout. – freakish

Répondre

3

Comme mentionné dans les commentaires, vous devez connaître les codes d'erreur, ce qui pourrait être reçue du serveur distant. Le std::string que vous recevez à partir d'un serveur distant contient 2 parties que vous avez dit,

Le problème est que ceux-ci sont identifiés par des chaînes, par exemple, « 0A01 » et contiennent également un message, et le code d'erreur nécessite un entier comme valeur.

Comme vous ne l'avez pas partagé le format du message d'erreur, je ne suis pas d'ajouter le code pour spiting il, diviser votre chaîne en 2 parties,

  1. Code d'erreur
  2. Message d'erreur

maintenant, vous pouvez convertir le code d'erreur de type std::string à int en utilisant std::stoi(error_code), permet donc dire

int error_code_int = std::stoi(string_to_hexadecimal(error_code)); 

Et pour std::error_category qui sert de classe de base pour nos messages d'erreur personnalisés, faites ceci,

std::string message_received = "This is the message which received from remote server."; 

struct OurCustomErrCategory : std::error_category 
{ 
    const char* name() const noexcept override; 
    std::string message(int ev) const override; 
}; 

const char* OurCustomErrCategory::name() const noexcept 
{ 
    return "Error Category Name"; 
} 

std::string OurCustomErrCategory::message(int error_code_int) const 
{ 
    switch (error_code_int) 
    { 
    case 1: 
     return message_received; 

    default: 
     return "(unrecognized error)"; 
    } 
} 

const OurCustomErrCategory ourCustomErrCategoryObject; 

std::error_code make_error_code(int e) 
{ 
    return {e, ourCustomErrCategoryObject}; 
} 

int main() 
{ 
    int error_code_int = std::stoi(string_to_hexadecimal(error_code)); // error_code = 0A01 
    ourCustomErrCategoryObject.message(error_code_int); 
    std::error_code ec(error_code_int , ourCustomErrCategoryObject); 
    assert(ec); 

    std::cout << ec << std::endl; 
    std::cout << ec.message() << std::endl; 
} 

La sortie ci-dessus exemple de travail est

Error Category Name : 0A01 
This is the message which received from remote server. 

Vous pouvez utiliser la fonction string_to_hexadecimal() de this post .

J'espère que maintenant vous pouvez modifier le code ci-dessus en fonction de vos besoins.

Edit 1:

Comme vous avez dit que:

Cela suppose le message dynamique est une valeur globale. Comment est-ce que je le passe à un objet std::error_category?

Vous pouvez voir que les deux std::error_code::assign et constructeur std::error_code::error_code prennent des paramètres de int pour le numéro de code d'erreur et error_category.Il est donc évident que std::error_code ne peut pas prendre le message dynamique.

Mais attendez, j'ai dit std::error_code prennent error_category comme argument dans le constructeur, donc est-il possible d'y assigner le message dynamique?

std::error_categoryaffirme que:

std::error_category sert de classe de base pour erreur spécifique types de catégorie.

Cela veut donc dire que le struct nous dérivé de std::error_category à la ligne suivante

struct OurCustomErrCategory : std::error_category 

peut avoir un membre de données et nous pouvons l'affecter via la fonction membre, notre struct deviendra comme ça,

struct OurCustomErrCategory : std::error_category 
{ 
    std::string message_received; 
    OurCustomErrCategory(std::string m) : message_received(m) {} 

    const char* name() const noexcept override; 
    std::string message(int ev) const override; 
}; 

et vous pouvez l'assigner comme ça partout où vous voulez,

const OurCustomErrCategory ourCustomErrCategoryObject("This is the message which received from remote server."); 
+0

Cela suppose que le message dynamique est une valeur globale. Comment est-ce que je le passe à un objet std :: error_category? – ruipacheco

+1

@ruipacheco: Vous pouvez stocker le message dans les membres de 'OurCustomErrCategory' et ajouter des méthodes pour les stocker si vous ne les connaissez que lorsqu'ils arrivent du réseau. Cela suppose que le mappage du code d'erreur au message est constant, c'est-à-dire que si deux codes d'erreur sont identiques, les messages seront identiques. – PaulR

+0

@ruipacheco Y at-il un problème dans le code, comment puis-je vous aider? –

0

Ne pas sous-classer le code d'erreur. Vous devez écrire votre propre catégorie d'erreur, qui mappe les entiers à vos erreurs spécifiques. Ceci est une description étape par étape sur la façon de le faire:

http://blog.think-async.com/2010/04/system-error-support-in-c0x-part-4.html

+0

Mais je n'ai pas d'entiers. J'ai deux chaînes et l'utilisateur final vérifiera toujours le code. – ruipacheco

+0

Vous pouvez toujours mapper les chaînes de code d'erreur entrantes à des entiers d'erreur: 'std :: code_erreur ec = code_erreur_erreur (errc_from_str (" 0A01 "));' – erenon

+0

Impossible de trouver errc_from_str(). – ruipacheco