2

私は Windows API をラップしており、エラー チェックを使いやすく便利なものにしたいと考えています。set現在、新しいエラーを処理する関数を備えたグローバル エラー オブジェクトがあります。このset関数は 4 つの引数を取ります。bool Error::set (const int code, const char * file, const char * const function, const int line);この関数は、ファイル、関数、および行の引数を使用して、適切にフォーマットされたメッセージで表示します。

エラーの設定を簡単にするために、マクロがあります。#define setError() error.set (GetLastError(), __FILE__, __FUNCTION__, __LINE__);これsetError()により、API 関数を呼び出した後に追加することで、いつでも API 関数が設定したエラーに応答することができます。

残念ながら、これによりコードは次のようになります。

SomeAPIFunction();
setError();
AnotherAPIFunction();
setError();

コンストラクターにも問題があります。

MyClass:MyClass()
    : a (SomeAPIFunction), b (AnotherAPIFunction)
{
    setError(); //what if both functions set an error?
}

ご覧のとおり、メンバー初期化構文を使用することで、実際に自分自身を制限しています。

これを修正する 1 つの方法は、すべての API 関数をラップすることです。

int someAPIFunction()
{
    int ret = SomeAPIFunction();
    setError();
    return ret;
}

エラー メッセージのfunction一部で、エラーの原因となった関数がわかります。もちろん、それはこれに対処するための最悪の方法でなければなりません。

解決策は、可変個引数テンプレートを使用することです。問題は、彼らをこのために働かせるために私が何をすべきかわからないということです. 最終的なコードは次のいずれかのようになると思います。

wrap<int, SomeAPIFunction (5)>();
wrap<int, SomeAPIFunction, 5>();
wrap<int, SomeAPIFunction> (5);

可変引数テンプレートの開始に関する記事を読んだことがありますが、このようなものを設定する方法がわかりません。誰かが私を正しい方向に向けることができますか?

同様の質問で次のことがわかりました。

#include <iostream>

template<void f(void)>
struct Wrap {
   void operator()() const {
      std::cout << "Pre call hook" << std::endl;
      f();
   }
};

namespace {
   void test_func() {
      std::cout << "Real function" << std::endl;
   }
}

const Wrap<&test_func> wrapped_test_func = {};

int main() {
   wrapped_test_func();
   return 0;
}

回答者は、これを十分に汎用的にするには可変個引数テンプレートが必要であると指摘しました。それは始まりですが、私は迷子になり、この問題に関する助けに感謝しています.

4

1 に答える 1

1

この構文で動作させることができると思います。

wrap(&SomeAPIFunction, arg1, arg2);

重要なのは、コンパイラが型推論を使用してテンプレート型パラメータを決定できるようにすることです。これらは急いでかなり乱雑になるためです。

コードは次のようになります。

template<typename TRet, typename... TArgs>
TRet wrap( TRet(WINAPI *api)(TArgs...), TArgs... args )
{
    return api(args...);
}

当然、マクロを使用して関数のアドレス演算子を非表示にし、文字列化を使用して関数名を格納し、ファイル名と行番号も格納して、それらすべてを実際の可変個引数関数に渡します。そのためには可変個引数マクロが必要です。実際、これらすべてを可変個引数マクロだけで、テンプレートなしで実行できますか?

于 2012-02-28T21:42:03.217 に答える