代码之家  ›  专栏  ›  技术社区  ›  Björn Pollex

声明要记录的类的模块名

  •  0
  • Björn Pollex  · 技术社区  · 15 年前

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

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

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

    提前谢谢!

    2 回复  |  直到 15 年前
        1
  •  2
  •   Georg Fritzsche    15 年前

    我希望这在课堂上是可能的。

    这在您的方法中是不可能的,必须在模板是其成员的命名空间中声明显式专门化。

    您没有说明实际使用的代码是什么样子,但是您应该能够让名称和重载解析为您工作(例如,从日志宏):

    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; }
    };
    
        2
  •  0
  •   Dmitry Yudakov    15 年前

    我不确定这个解决方案应该有多简单,这里有一个我用过几次的非常简单的解决方案。

    有一个基类 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;
        }
    };