라이브 로깅 프레임 워크 (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
클래스를 템플릿으로 만들지 않고도이 작업을 수행 할 수 있습니까? 코드베이스는 전혀 템플릿 화되지 않았고 지루한 작업이 많아 질수록이 경로를 따라 가기를 꺼립니다.
템플릿을 기능 수준 범위로 유지함으로써 해결할 수 있다면 해결책을 찾게되어 매우 기쁩니다. 함수 포인터도 받아 들일 만하지만 가변성 템플릿 함수의 주소를 얻는 가능성에 대해서는 잘 모르겠습니다.
감사합니다.
google에서 CRTP 확인 – cooky451
형식 문자열 및 구현의 인수가 필요합니까, 아니면 형식화 결과가 필요합니까?형식 지정의 결과 이상을 필요로하는 경우 중간 양식이 있습니까? 로거 또는 포맷터의 구현 방식은 어떻게 다릅니 까? – Yakk
문제는 템플릿을 컴파일러에서 인스턴스화해야한다는 것입니다. 즉, 컴파일러는 * 함수 템플릿 *에서 실제 함수 *를 만들어야합니다. 따라서 각 번역 단위에서 함수 템플릿을 구현해야합니다 (인스턴스화해야하는 경우). 함수 템플릿은 가상 클래스가 될 수 없습니다. 왜냐하면 기본 클래스의 함수를 사용하려면 (모든) 파생 클래스의 오버라이드를 인스턴스화해야하고 가상 함수로 구현할 수있는 별도의 컴파일로는 불가능합니다. – dyp