0

我目前正在向我们的日志库添加一些功能。其中之一是可以为一个类声明一个模块名,该类会自动预先添加到从该类中写入的任何日志消息中。但是,如果没有提供模块名称,则不会添加任何内容。目前我正在使用一个具有返回名称的静态函数的特征类。

template< class T >
struct ModuleNameTrait {
    static std::string Value() { return ""; }
};

template< >
struct ModuleNameTrait< Foo > {
    static std::string Value() { return "Foo"; }
};

可以使用辅助宏定义此类。缺点是模块名称必须在类之外声明。我希望这在课堂上是可能的。此外,我希望能够使用预处理器指令删除所有日志记录代码。我知道使用 SFINAE 可以检查模板参数是否具有某个成员,但由于其他人对模板不像我那么友好,因此必须维护代码,我正在寻找一种更简单的解决方案。如果没有,我将坚持使用特征方法。

提前致谢!

4

2 回答 2

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; }
};
于 2010-03-25T11:29:55.490 回答
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;
    }
};
于 2010-03-25T11:35:48.300 回答