Declare module name of classes for logging
I currently am adding some features to our logging-library. One of these is the possibility to declare a module-name for a class that automatically gets preprended to any log-messages writing from within that class. However, if no module-name is provided, nothing is prepended. Currently I am using a trait-class that has a static function that returns the name.
template< class T >
struct ModuleNameTrait {
static std::string Value() { return ""; }
};
template< >
struct ModuleNameTrait< Foo > {
static std::str开发者_StackOverflowing Value() { return "Foo"; }
};
This class can be defined using a helper-macro. The drawback is, that the module-name has to be declared outside of the class. I would like this to be possible within the class. Also, I want to be able to remove all logging-code using a preprocessor directive. I know that using SFINAE one can check if a template argument has a certain member, but since other people, that are not as friendly with templates as I am, will have to maintain the code, I am looking for a much simpler solution. If there is none, I will stick with the traits approach.
Thanks in advance!
I would like this to be possible within the class.
This is not possible with your approach, explicit specializations have to be declared in the namespace of which the template is a member.
You don't say how the actual using code looks like, but you should be able to let name and overload resolution work for you (e.g. from a logging macro):
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; }
};
If you want to define name()
only in classes and not outside, there is of course no need for templates or overloads:
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; }
};
I'm not sure how simple the solution should be, here's a very simple one I used a few times.
There is a base class ClassName
with something like:
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
And other class would inherit it, giving its name:
class Session : virtual public ClassName
{
public:
Session() : ClassName("Session")
{
}
void func()
{
LOG << "Some log here" << endl;
}
};
精彩评论