ライブ ロギング フレームワーク (Apache) によってコードが緊密に結合され、単体テストの記述が非常に難しくなるため、大規模なコードベースからロギング コードをモジュール化しようとしています。仮想テンプレート関数を使用できないという事実に固執しています。私の現在のアプローチは、次のように要約できます。
// Context.h
struct Logger
{
template <typename... Args>
void operator()(const char* aFormat, Args&&... aArgs)
{
// This function would ideally be virtual.
// Is there a funky way to get this function to call
// a derived class' implementation instead.
std::cerr << "I don't want to see this printed" << std::endl;
}
};
class Context
{
public:
Context(const Logger& aLogger)
: iLogger(aLogger)
{
}
template <typename... Args>
void DEBUG(const char* aFormat, Args&&... aArgs)
{
iLogger(aFormat, aArgs...);
}
private:
const Logger& iLogger;
};
// MyType.h
#include "Context.h"
class MyType
{
public:
MyType(Context& aCtx)
: iCtx(aCtx)
{
DEBUG("> ctor");
DEBUG("< ctor. this=%p", this);
}
private:
template <typename... Args>
void DEBUG(const char* aFormat, Args&&... aArgs)
{
iCtx.DEBUG(aFormat, aArgs...);
}
Context& iCtx;
};
// main.cpp
#include "MyType.h"
template <typename... Args>
static void StdErrLog(const char* aFormat, Args&&... aArgs)
{
fprintf(stderr, aFormat, aArgs...);
}
struct StdErrLogger : public Logger
{
// This function never gets called because it's not virtual.
template <typename... Args>
void operator(const char* aFormat, Args&&... aArgs)
{
StdErrLog(aFormat, aArgs...);
}
}
int main(...)
{
StdErrLogger logger; // For unit tests this could be 'EmptyLogger' for example.
Context ctx(logger);
MyType t(ctx);
}
これまでのところ、とても近いです。クラスをテンプレート化せずにこれを機能させるためにできることはありContext
ますか? コード ベースはまったくテンプレート化されておらず、面倒な作業が多いため、このルートをたどるのは非常に気が進まない.
テンプレートを関数レベルの範囲に抑えることでそれが可能であれば、解決策を見てとてもうれしく思います. 関数ポインターも受け入れられますが、可変個引数テンプレート関数のアドレスを取得できるかどうかはわかりません。
ありがとう