4

プロジェクトにFormatMessage()を使用する必要がありますが、その恐ろしいインターフェイスが好きではありません。置換パラメーターを許可しながら、それを整理するファサードを知っている人はいますか?

は FastFormat の紹介 の 2 番目の部分を読み、 FormatMessage()の拡張機能を作成することを検討しています(または、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 つの問題があります。

  • int, std::string, void*- ではない任意の型を簡単に渡すことができるため、型安全ではありません。const char*
  • 引数の数と、エラーを表すフォーマット文字列に必要な数が一致しないのは簡単です。

型安全性の観点からFastFormatの機能を考えると、そのメカニズムに従ってFormatMessage()を処理する方法があるかどうかを知りたいです。

4

2 に答える 2

1

フォーマット文字列に挿入されるパラメーターの数はコンパイラーによってチェックできないため、コンパイル時にこれを完全にタイプセーフにすることは不可能です。

さまざまな数の挿入されたパラメーターに対していくつかのオーバーロードを用意し、挿入された値を のような柔軟なもので指定するだけで、ほとんどの方法でそこに到達できますboost::any。したがって、2 つのパラメーターのオーバーロードは次のようになります。

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

から値を取得するときarg1に、間違った型を取得しようとすると、boost がスローするため、書式文字列を調べて、各引数から必要な型を取得しようとするだけです。

あるいは、テンプレートと 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
}

そうすれば、渡された型がストリーミングできる限り、各引数から文字列を取得できます。フォーマット文字列が文字列のみを挿入することを期待している限り、他に何も必要ありません。

于 2009-05-10T11:42:02.040 に答える
0

C++ フォーマット ライブラリを使用すると、 によって返されるエラー コードに対応するネイティブ Windows エラー メッセージGetLastError()と、 によって指定されるエラーに対応する POSIX エラー メッセージをフォーマットできますerrno。例えば:

// This throws a WindowsError with the description
//   cannot open file 'madeup': The system cannot find the file specified.
// or similar (system message may vary).
const char *filename = "madeup";
LPOFSTRUCT of = LPOFSTRUCT();
HFILE file = OpenFile(filename, &of, OF_READ);
if (file == HFILE_ERROR)
  throw fmt::WindowsError(GetLastError(), "cannot open file '{}'", filename);

FormatMessageAPI関数を使用してWindowsのエラーメッセージを取得します。fmt::format_windows_error例外をスローしないエラー メッセージをフォーマットすることもできます。詳細については、システム エラーを参照してください。

免責事項: 私は C++ 形式の作成者です

于 2015-02-19T01:54:50.263 に答える