2009-05-10 9 views
3

FormatMessage()をプロジェクトに使用する必要がありますが、私は恐ろしいインターフェイスが気に入らないのです。誰かが交換用パラメータを許可しながらそれを整理するファサードを知っていますか?Windows用の安全で柔軟なファサードFormatMessage

私はちょうどsecond part of the FastFormat introductionを読み、FormatMessage()の拡張子を書いて(あるいは、彼らが作品に1を持っている場合FastFormatプロジェクトチームを求めて)検討していますが、何がありますので、もし私が、できるだけ早く何かを得ることに熱心ですそれ以外にはまともなことは、おそらく私は代わりにそれをつかむだろう。私が欲しいもの

は、次のようなコードを書くことができるようにすることです。結果を与えるだろう

HINSTANCE netevent = ::LoadLibrary("netevent.dll"); 
std::string msg = LookupError(netevent, EVENT_SERVICE_START_FAILED_II, 
    "child-svr", "parent-svr", "ship happens"); 
::puts(msg.c_str()); 

The child-svr service depends on the parent-svr service which failed to start be cause of the following error: 
ship happens 

私が構築した現在のラッパーは、インターフェースを持っています

std::string LookupError(HINSTANCE hinst, DWORD id, ...); 

これには2つの問題があります。

  • それはそれはどのようなタイプ合格するのは簡単なので、タイプセーフではありません - intstd::stringvoid* - const char*
  • ではありませんそれはエラーを表すフォーマット文字列で必要な数と引数の数を不一致するのは簡単です

は、型の安全性の面でFastFormatの能力を考えると、私はFormatMessage()に対処するためのメカニズムを追跡する方法があるかどうかを知りたいです。

+3

のようなものを書くことができますか?何? –

+0

Doh!ごめんなさい。瞬時にそれを修正します... – dcw

答えて

1

フォーマット文字列に挿入するパラメータの数をコンパイラでチェックできないため、これをコンパイル時に真に型保証することは不可能です。

挿入されたパラメータの数が異なるためにいくつかのオーバーロードが発生し、挿入された値をboost::anyのような柔軟な値で指定するだけで、ほとんどの方法が得られます。だから、2つのパラメータのオーバーロードは、次のようになります。

std::string FormatMessage(HINSTANCE hinst, DWORD id, const boost::any &arg1, const boost::any &arg2); 

あなたはarg1から値を取得するとき、あなたが間違った型を取得しようとするので、あなただけの書式文字列を調べて取得しようとする必要がある場合、ブーストがスローされます各引数から必要な型。

また、非常に柔軟なバージョンのテンプレートとstd :: ostringstream(またはboost :: lexical_cast)を使用することもできます。再び、引数の数が変化することができるように過負荷が存在することになるので、ここでは単一引数バージョンです:あなたが渡されたタイプ限り各引数から文字列を取得することができます

template <class TArg1> 
std::string FormatMessage(HINSTANCE hinst, DWORD id, const TArg1 &arg1) 
{ 
    std::ostringstream arg1Stream; 
    arg1Stream << arg1; 
    std::string arg1String = arg1Stream.str(); 

    DWORD_PTR argArray = reinterpret_cast<DWORD_PTR>(arg1String.c_str()); 

    // ... etc 
} 

そのようにストリーミングすることができ、書式文字列が文字列だけを挿入することを期待している限り、他のものは必要ありません。

+1

興味深い考えです。 FormatMessage()には、argsのva_listか、32ビットのargの配列が必要です。ですから最初のケースではバリデーション関数が必要ですが、これは記述した関数のような関数内で呼び出すことができ、boost :: anyは型安全性を処理します。あるいは、引数の配列を直接構築することもできます。しかし、私がFastFormatに興味を持った理由の1つは、任意の型の引数を扱うことができることです。これは、FormatMessage()を呼び出す前にすべての型を渡してchar *に変換できることを意味します。私はboost :: anyがそれを許可するとは思わない。 – dcw

+0

更新を見る、より柔軟な何か。 –

0

The C++ Format libraryは、GetLastError()によって返されるエラーコードに対応するネイティブWindowsエラーメッセージと、errnoによって示されるエラーに対応するPOSIXエラーメッセージを許可します。例:

FormatMessage API関数を使用すると、Windowsエラーメッセージが表示されます。また、例外をスローしないfmt::format_windows_errorでエラーメッセージをフォーマットすることもできます。詳細はSystem Errorsを参照してください。

免責事項:私はC++の書式