2010-03-25 42 views
0

我目前正在爲我們的日誌記錄庫添加一些功能。其中之一就是可以聲明一個模塊名稱,該模塊名稱可以自動預先寫入該類中寫入的任何日誌消息。但是,如果沒有提供模塊名稱,則不會有任何前提。目前我正在使用一個具有返回名稱的靜態函數的特徵類。聲明要記錄的類的模塊名稱

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

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

該類可以使用助手宏來定義。缺點是,模塊名稱必須在類之外聲明。我希望這可以在課堂上進行。另外,我希望能夠使用預處理器指令移除所有日誌記錄代碼。我知道使用SFINAE可以檢查一個模板參數是否具有某個成員,但是由於其他人不像模板那樣友好,因此必須維護代碼,所以我正在尋找一個更簡單的解決方案。如果沒有,我會堅持特質方法。

提前致謝!

回答

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; } 
}; 
+0

這是完美的!有時候我沒有看到樹林,我正在想辦法變得複雜。謝謝! – 2010-03-25 12:00:03

+0

我知道這個問題:) – 2010-03-25 14:08:42

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; 
    } 
}; 
+0

我也考慮過這種方法,但我放棄了它,因爲它不能輕易被定義或預處理器指令取消。 – 2010-03-25 11:56:33

+0

這取決於很少的ifdefs,你可以將整個事物侷限於空類的繼承,而不用調用它的函數。 – 2010-03-25 12:23:57