2017-01-18 7 views
0

例外とエラーコードの使用方法と、それぞれが適切な場合のいくつかの説明を読んでいます。私は私の場合の例外を信じstlにエラーコードの例外がありますか?

は優れているが、私はある特定の問題があります:私はSTD :: runtime_errorを投げる(「これは誤りである」)、その後、私はそれをキャッチした場合

を、私は見つけることができませんエラーは何ですか、私はちょうどエラーがあったことを理解しています。

enum errorCodes 
{ 
     error_1, 
     error_2, 
     error_3 
} 

try 
{ 
    throw std::runtime_error(error_1,"can not do the job!"); 
} 
catch (std::runtime_error & err) 
{ 
    switch (err.errorCode) 
    { 
     case error_1: 
      // I can not contunue, so re throw it 
      rethrow err; 
     case error_2: 
      // it is not important for me, so I can continue 
      break; 
     case error_3: 
      //Oh, I need to do something before continue 
      re_init(); 
      break; 
     default: 
      rethrow err; 
    } 

私ができる:私は探しています何

は、このようないくつかの事、私はそれをキャッチするときので、後に、私は、エラーコードを確認することができ、私はそれにエラーコードをスローして追加することができます例外でそのような例外を記述しますが、これを行う前に、STLやBOOSTにこの種の例外が存在するかどうか疑問に思っていますか?

は、これを行うのいずれかのより良い方法(私は例外の異なる種類をキャッチ、例外の異なる種類をスローしないように興味を持っては、私の視点から解決策がないからである。

+0

* "異なるタイプの例外を投げるのは興味がありませんので、異なるタイプの例外を捕まえることは私の立場からの解決策ではありません。" *しかし、IMOは行く方法です。 (あなたの例では 'error_2'と' error_3'のみ) – Jarod42

+0

@ Jarod42しかし、それはあなたが異なるタイプの例外を開発して投げる必要があることを意味します。私は2つのエラーがあるかもしれません:ファイル名が有効ではなく、メモリがないので、ファイルの内容をバッファに読み込む単純なタスクであっても、2種類の例外が必要です。 – mans

+0

私はエラーコード([Demo](http://coliru.stacked-crooked.com/a/45ee82736f244a1b)の上で特定の例外([Demo](http://coliru.stacked-crooked.com/a/6b5d8f52b7bd966e) )) – Jarod42

答えて

2

はい、ありますstd::system_error。それはですstd::runtime_error由来。それはかなりのUnix-土地志向のだが、それは一般的にはエラーコードをサポートし、そして私はあなたがそのように使用することを示唆している。


次のコードは、アプリケーションのために自分のエラーカテゴリを定義する方法を示しています特定のエラーコード:

#include <string> 
#include <system_error> 
#include <typeinfo> 

namespace my{ 
    struct Error_code 
    { 
     enum Enum 
     { 
      error_1 = 101, 
      error_2 = 102, 
      error_3 = 103 
     }; 
    }; 

    class App_error_category 
     : public std::error_category 
    { 
    using Base = std::error_category; 
    public: 
     auto name() const noexcept 
      -> char const* 
      override 
     { return "App error"; } 

     auto default_error_condition(int const code) const noexcept 
      -> std::error_condition 
      override 
     { (void) code; return {}; } 

     auto equivalent(int const code, std::error_condition const& condition) const noexcept 
      -> bool 
      override 
     { (void) code; (void) condition; return false; } 

     // The intended functionality of this func is pretty unclear. 
     // It apparently can't do its job (properly) in the general case. 
     auto equivalent(std::error_code const& code, int const condition) const noexcept 
      -> bool 
      override 
     { return Base::equivalent(code, condition); } 

     auto message(int const condition) const 
      -> std::string 
      override 
     { return "An application error occurred, code = " + std::to_string(condition); } 

     constexpr 
     App_error_category(): Base{} {} 
    }; 

    auto app_error_category() 
     -> App_error_category const& 
    { 
     static App_error_category the_instance; 
     return the_instance; 
    } 

    class App_error 
     : public std::system_error 
    { 
    using Base = std::system_error; 
    public: 
     auto app_error_code() const 
      -> Error_code::Enum 
     { return static_cast<Error_code::Enum>(code().value()); } 

     App_error(Error_code::Enum const code) 
      : Base{ code, app_error_category() } 
     {} 

     App_error(Error_code::Enum const code, std::string const& description) 
      : Base{ code, app_error_category(), description } 
     {} 
    }; 

} // namespace my 

void foo() 
{ 
    try 
    { 
     throw my::App_error(my::Error_code::error_1, "can not do the job!"); 
    } 
    catch(my::App_error const& x) 
    { 
     switch(x.app_error_code()) 
     { 
     case my::Error_code::error_1: 
      // I can not contunue, so re throw it 
      throw; 
     case my::Error_code::error_2: 
      // it is not important for me, so I can continue 
      break; 
     case my::Error_code::error_3: 
      //Oh, I need to do something before continue 
      //re_init(); 
      break; 
     } 
    } 
} 

#include <iostream> 
#include <stdlib.h>  // EXIT_SUCCESS, EXIT_FAILURE 
using namespace std; 
auto main() 
    -> int 
{ 
    try 
    { 
     foo(); 
     return EXIT_SUCCESS; 
    } 
    catch(exception const& x) 
    { 
     cerr << "!" << x.what() << endl; 
    } 
    return EXIT_FAILURE; 
} 

は、Visual C++ 2015とMinGWのG ++ 6.4.0の両方で、このエラーコードを使用するよりも、それが特定の例外クラスを定義するために、より実用的です一般的には、出力に

 
!can not do the job!: An application error occurred, code = 101 

を生成します。しかし、システムエラーコードの場合、例外を除いてこれらのコードを渡すほうが現実的です。 の場合、は、std::system_categoryが非常に適しているため、上記の複雑さは回避できます。

簡潔に言えば、ここでの複雑さは、フローと一緒ではなく、ある程度電流とは逆の方向からのあなたの要求に由来します。

+0

私はどのようにカスタムエラーコードを作成し、システム生成エラーコードと衝突していないことを確認できますか? – mans

+0

@mans:あなたは「カテゴリ」を使用しています。私はALMOSTが動作するいくつかのコードを作成しました。おそらくあなたはそれを修正する方法を理解することができます:https://godbolt.org/g/WMhvDU –

+0

@mans:[コンストラクタのドキュメント](http://en.cppreference。 com/w/cpp/error/system_error/system_error)。基本的に型付きコードと[エラーカテゴリ](http://en.cppreference.com/w/cpp/error/error_category)があります。エラーカテゴリは、エラーコード値の意味を定義します。 –

2

std::system_errorをそのまま使用することを検討してください。

注前者は値ではなくより参照によって例外がスローされますので、引数を指定せずに、単にthrow;を使用すると、(あなたがthrow err;を使用しているように見える)の再投げあなたの例外のはるか良い方法であることを :後者はオブジェクトをスライスする可能性があります。

+1

"rethrow err"はC++コードとして構文的に無効なので、疑似コードとして意図しています。 –

+0

私はそこに "見た目"を埋め込んで私の**をカバーしました;-)あなたは私が 'std :: system_error'への参照にニックネームを付けるようにすれば、あなたの答えをアップアップするのはどうですか? (私はちょうどやった)。 – Bathsheba

関連する問題