2010-07-06 129 views
3

我創造了我的圖書館日誌工具,並取得了一些不錯的宏,例如:使用C++宏來檢查變量是否存在

#define DEBUG myDebuggingClass(__FILE__, __FUNCTION__, __LINE__) 
#define WARING myWarningClass(__FILE__, __FUNCTION__, __LINE__) 

其中myDebuggingClass和myWarningClass都有一個重載< <運營商,以及用日誌消息做一些有用的事情。

現在,我有一個用戶將被超載稱爲「微件」的一些基礎類的,我想這些定義改變爲更多的東西一樣:

#define DEBUG myDebuggingClass(__FILE__, __FUNCTION__, __LINE__, this) 
#define WARNING myWarningClass(__FILE__, __FUNCTION__, __LINE__, this) 

這樣,當用戶撥打「DEBUG < < 「有些消息」; '我可以檢查「this」參數是否dynamic_casts到一個Widget,如果可以的話,我可以用這些信息做一些有用的事情,如果沒有的話,我可以忽略它。唯一的問題是我希望用戶能夠從非成員函數(例如main())發出DEBUG和WARNING消息。但是,由於這個簡單的宏,用戶只會得到一個編譯錯誤,因爲「this」不會在類成員函數之外定義。

最簡單的解決方案是隻定義單獨的WIDGET_DEBUG,WIDGET_WARNING,PLAIN_DEBUG和PLAIN_WARNING宏,並向用戶記錄差異,但如果有辦法解決這個問題,那將非常酷。有沒有人看到做這種事情的任何伎倆?

回答

3

聲明全局Widget* const widget_this = NULL;,並在Widget類保護的成員變量widget_this,初始化爲this,並做

#define DEBUG myDebuggingClass(__FILE__, __FUNCTION__, __LINE__, widget_this)

+0

這應該起作用。 – 2010-07-06 22:09:52

+4

我應該注意到這個答案在很多方面都是邪惡的。它使用了我不喜歡的宏,我覺得令人討厭的可變陰影和受保護的數據成員,我通常會避免(儘管我不反對)。這個解決方案是對你所問的問題最快最直接的回答,但這並不意味着它就是你的問題的答案。 – 2010-07-06 22:11:13

+0

我喜歡@ MSalters的解決方案比這個更好。 – 2012-10-31 22:27:28

2

宏基本上是由預處理器進行直接的文本替換。有沒有辦法讓宏知道從它被稱爲做排序檢測你感興趣的內容。

最好的解決辦法可能是單獨的宏爲你懷疑。

0

我能想到的可能得到這個工作的唯一方法是定義一個全局變量:

Widget * this = NULL; 

如果連編譯(我有我的懷疑,但沒有一個編譯器測試它),成員函數將使用最近的作用域變量(真正的his指針),其他所有變量都將得到空值。每個人的快樂(這麼說......)

+0

它不會編譯。 – Puppy 2010-07-06 21:34:52

1

我不認爲你可以用宏做到這一點。您可以可能管理與SFINAE做到這一點,但使用SFINAE代碼(至少直接地)是很難寫,很難調試,而且幾乎不可能對任何人,但專家閱讀或理解。如果你真的想這樣做,我會試着看看你是否可以讓Boost enable_if(或其親屬)來處理至少一部分髒活。

......至少在我見過的每一種情況下,我都很難想象它是否會成爲其他人。

+0

除了通過使用enable_if你正在寫SFINAE依賴代碼,哪種計數你的論點,因爲使用enable_if是相當容易的。它不像enable_if隱藏這個事實,因爲只使用enable_if是不夠的,你必須嘗試訪問它的:: type字段,你必須以這種方式觸發SFINAE。但實際上,我不認爲SFINAE會起作用,因爲'this'必須被訪問,當它不可用時,這不是SFINAE問題。我可能是錯的,但我沒有看到解決這個問題的辦法。 – 2010-07-06 22:00:12

+0

@Noah:也許你應該仔細閱讀一下,仔細看看那裏的「(至少直接)」部分。 'enable_if'允許你間接*使用它。我承認我不確定* SFINAE會爲此工作(這就是爲什麼我說「可能」),但我仍然不確定它不能。 – 2010-07-06 22:23:35

+0

好吧,正如我所說的,enable_if不允許您間接使用SFINAE。當你調用enable_if時,你實際上直接使用它。在enable_if元函數中沒有任何SFINAE;它只是一個簡單的結構。所有的SFINAE都由編寫客戶代碼的人員在呼叫現場完成。 enable_if只是一個很好的解釋性名稱,它使SFINAE代碼的目的更易於理解。它不是通過inttemplate T::type f(); 2010-07-06 22:37:00

1

通過solipist的啓發,但在執行稍微簡單:

class Widget { 
    protected: 
    ::myDebuggingClass myDebuggingClass(char const* file, char const* function, int line) { 
    return ::myDebuggingClass(file, function, line, this); 
    } 
    // ... 

這消除了對陰影變量的需求;它依賴於簡單的類名查找規則。

0

您可以使用弱引用來檢測變量或函數是否存在。 例如: 檢測INT一個存在:

INT一個屬性((弱));如果(a) 存在 否則 不存在