我目前正在为我们的日志库添加一些功能。其中之一是可以为类声明一个模块名称,该类自动获得预先渲染到从该类中写入的任何日志消息。但是,如果未提供模块名称,则不会添加任何内容。目前我正在使用一个具有返回名称的静态函数的特征类。
template< class T >
struct ModuleNameTrait {
static std::string Value() { return ""; }
};
template< >
struct ModuleNameTrait< Foo > {
static std::string Value() { return "Foo"; }
};
可以使用辅助宏来定义此类。缺点是,必须在类之外声明模块名称。我想在课堂上这是可能的。此外,我希望能够使用预处理器指令删除所有日志代码。我知道使用SFINAE可以检查模板参数是否具有某个成员,但由于其他人(我不熟悉模板)将需要维护代码,我正在寻找一个更简单的解决方案。如果没有,我将坚持特质方法。
提前致谢!
答案 0 :(得分:2)
我希望在课堂上可以做到这一点。
使用您的方法无法做到这一点,必须在模板所属的命名空间中声明显式特化。
您没有说明实际使用代码的样子,但您应该能够让名称和重载分辨率适用于您(例如从记录宏):
template<class T> const char* const name(const T&) { return ""; }
class X;
const char* const name(const X&) { return "X"; }
struct X {
// prints "X"
void f() { std::cout << name(*this) << std::endl; }
};
struct Y {
static const char* const name(const Y&) { return "Y"; }
// prints "Y"
void f() { std::cout << name(*this) << std::endl; }
};
struct Z {
// prints ""
void f() { std::cout << name(*this) << std::endl; }
};
如果您只想在课程中而不是在课堂外定义name()
,那么当然不需要模板或重载:
const char* const name() { return ""; }
struct X {
static const char* const name() { return "X"; }
// prints "X"
void f() { std::cout << name() << std::endl; }
};
struct Y {
// prints ""
void f() { std::cout << name() << std::endl; }
};
答案 1 :(得分:0)
我不确定解决方案应该有多简单,这是一个非常简单的解决方案,我曾经使用过几次。
有一个基类ClassName
,类似于:
class ClassName
{
string name;
public:
ClassName( string strName = "" ) : name(strName)
{
if( strName.length() )
strName += ": ";
}
string getName()
{
return name;
}
};
#ifdef _DEBUG
#define LOG cout << getName()
#else
#define LOG cout
#endif
其他类会继承它,并给出它的名字:
class Session : virtual public ClassName
{
public:
Session() : ClassName("Session")
{
}
void func()
{
LOG << "Some log here" << endl;
}
};