2015-09-11 9 views
5

私のプログラムの先頭には、例外ハンドラがあります。
それは、このようなものになります。私はより一般的なアプローチを取るしたいのですが、より多くの例外タイプ、
を取得したよう簡略化された関数テンプレートと同様のcatch節を書くことはできますか?

try{ 
    //majority of program 
} 
catch(...){ 
    Handle_All_Exceptions(); 
} 


void Handle_All_Exceptions(){ 
    try{throw;} 
    catch(TypeA const& e){Handle(e)  ;} 
    catch(TypeB const& e){Handle(e)  ;} 
    catch(TypeC const& e){Handle(e)  ;} 
    catch(TypeD const& e){Handle(e)  ;} 
    catch(...)   {Handle_Unknown();} 

} 

void Handle(TypeA const& e){ 
    //... 
} 
void Handle(TypeB const& e){ 
    //... 
} 
void Handle(TypeC const& e){ 
    //... 
} 
void Handle(TypeD const& e){ 
    //... 
} 
void Handle_Unknown(){ 
    //... 
} 

を。
汎用プログラミングをHandle_All_Exceptionsにどのように適用できますか?


このようなものは、C++の新しいバージョンでは可能でしょうか?

catch(auto e){Handle(e)}; 
catch(...){Handle_Unknown();} 
+0

例外に共通の基本クラスがありますか? – robert

+0

@robert、いいえ、しかし、私はstd :: exceptionを継承した方が良いアプローチかもしれません。 –

+1

@TrevorHickeyは、基本クラス(http://en.cppreference)のstd :: runtime_errorを考慮することをお勧めします。com/w/cpp/error/runtime_error –

答えて

0

言語とその例外システムに大きな変更を加えることはできません。 catch節ハンドラと関数パラメータは構文的に似ているかもしれませんが、動作は全く異なります。考えてみましょう:

つまり
struct up {}; 
struct down { constexpr down(up) noexcept {} }; 

void func(down const&) {} 
void except() 
{ 
    try { 
     throw up {}; 
    } catch(down const&) {} 
} 

int main() 
{ 
    func(up {}); // fine 
    except(); // exception `up` escapes 
} 

Coliru

down const&ハンドラはタイプdownのか明確種類の例外オブジェクトにバインドする一方down const&パラメータは、downから転換あるものを受け入れます、公開されたは、からを派生したものです。

ここで大きな違いは、 'convertible to'という形式の関係がいろいろな形をとることです。この例ではコンバージョンコンストラクタを使用しましたが、代わりにupのコンバージョン演算子を使用できました。 「(公然とはっきりしない)由来の」は、直接的な方法で、そしてプログラム全体で、派生型が定義されていればどこでも正確に1つの場所でのみ選択することができます。これは、別々のコンパイルを考慮した場合に重要です。次のプログラムを考えてみましょう:

// a.cpp 

// defined in b.cpp 
void throws() noexcept(false); 

template<typename X> 
concept bool Fooable = requires(X x) { x.foo(); } 

int main() 
{ 
    try { 
     throws(); 

     // imaginary syntax for catching models of a concept 
    } catch(Fooable const&) {} 
} 

// b.cpp 

// defined in c.cpp 
struct other; 

struct model { 
    void foo() {} 
    other* foo(int) { return nullptr; } 
    void bar() {} 
}; 

void throws() noexcept(false) 
{ throw model {}; } 

// c.cpp omitted 

b.cppがコンパイルされると、コンパイラはa.cppは「あなたがx.foo()できる投げているそのオブジェクトのですか?」質問をすることを知る方法はありません。それにもかかわらず、その事実を悲観的に記録しなければならない(現在の規則の下で、同じ方法で「由来する」関係があれば、どこかに記録される)。また、完全なプログラムがそれを必要としないにもかかわらず、がx.bar()の能力があるという事実を記録すべきでしょうか? x.foo(0)->baz()の代わりにFooableをテストしたらどうなりますか? otherが、その式が意味を成すように定義された場合、どこに、いつ、どのように記録されるだろうか?どのようにmodelotherが別々に定義され、それぞれが他のものについて(多くの)知らないことに注意してください。

あなたが求めているのはまったく不可能ではありませんが、私たちが現在持っているシステムとはかなり違って見えると思います。現在のルールの下では、例外のジェネリックプログラミングはこれまでのところできません。古いクラスの階層を使用することは、最も抵抗の少ないパスです。

関連する問題