2016-12-31 109 views
1

我想利用類構造函數和解構函數來通過RAII成語在我的日誌文件中表示和格式化作用域。使用單個#define,它會打印「{」並增加全局縮進級別,以便下一個記錄行將在該縮進級別打印。防止解構宏定義的匿名變量,直到範圍結束

LogScopeRAII應該打印「}」並自然減少全局縮進級別,因爲它在Foo()的末尾超出了範圍。但是,我所看到的行爲是LogScopeRAII在構建後立即被解構。

假設:我認爲這個問題是一個正在上分配的RHS創建LogScopeRAII(因而匿名?),並在該行的末尾被銷燬,但我不知道該怎麼辦關於。我認爲LOG_ANONYMOUS_VARIABLEVSCOPE_F會做到這一點,並導致它堅持下去,但事實並非如此。

問題:如何阻止LogScopeRAII被解構,直到調用函數超出範圍?

/* Header */ 
LogScopeRAII::LogScopeRAII(Verbosity verbosity, const char* file, unsigned line, const char* format, ...) 
{ 
    // ... 
    // print "{" and then increase an indentation global var 
} 

LogScopeRAII::~LogScopeRAII() 
{ 
    // ... 
    // print "}" and then decrease the indentation global var 
} 

#define LOG_ANOMYMOUS_VARIABLE(str) LOG_CONCAT(str, __LINE__) 

#define VSCOPE_F(verbosity, ...) \ 
LogScopeRAII LOG_ANONYMOUS_VARIABLE(raii) = \ 
((verbosity) > verb_cutoff() ? LogScopeRAII() : LogScopeRAII{verbosity, __FILE__, __LINE__, __VA_ARGS__} 

#define SCOPE_F(verbosity_name, ...) VSCOPE_F(Verbosity_ ## verbosity_name, __VA_ARGS__) 

#define SCOPE_FUNCTION(INFO) SCOPE_F(verbosity_name, __FUNCTION__) 

/* Implementation */ 
void Foo() 
{ 
    SCOPE_FUNCTION(INFO) // print "{" and increase indentation 
    for (size_t i = 0; i < 3; ++i) 
    { 
     // do work 
     LOG(INFO, "Work logged"); 
    } 
    // print "}" and decrease indentation 
} 

希望的輸出:

{ Foo() 
    "Work Logged" // Note indentation 
} 0.23 s: Foo() 

編輯:煮ISSUE DOWN

的它的關鍵是這樣的:所述三元似乎並不奏效。

這工作:

LogScopeRAII a(LogScopeRAII{ Verbosity_INFO, __FILE__, static_cast<unsigned>(__LINE__), "" }); 

但這並不:

LogScopeRAII a(((Verbosity_INFO) > indent) ? LogScopeRAII() : LogScopeRAII{ Verbosity_INFO, __FILE__, static_cast<unsigned>(__LINE__), "" }); 

我得到:

{ 
} 
Work logged 
Work logged 
Work logged 
} 
constructCounter: 1 
destructCounter: 2 
Exiting... 
+1

餡這個在這一點上宏是有點爲時過早。在實際的代碼中分解出來,按照你想要的方式工作,然後根據需要添加宏。 –

+0

請參閱編輯。接受你的建議。似乎三元不工作? – Stradigos

+1

也許LogScopeRAII的移動結構被打破。 「工作版本」將隱藏由於複製影響而導致的問題,但是沒有使用條件運算符版本的副本。至少需要在析構函數中有代碼才能發出'}',如果這是一個已經被移出的臨時文件等。 –

回答

1
#define VSCOPE_F(verbosity, ...) \ 
LogScopeRAII LOG_ANONYMOUS_VARIABLE(raii) = \ 
((verbosity) > verb_cutoff() ? LogScopeRAII() : LogScopeRAII{verbosity, __FILE__, __LINE__, __VA_ARGS__} 

應該

#define VSCOPE_F(verbosity, ...) \ 
LogScopeRAII LOG_ANONYMOUS_VARIABLE(raii) \ 
(((verbosity) > verb_cutoff() ? LogScopeRAII() : LogScopeRAII{verbosity, __FILE__, __LINE__, __VA_ARGS__}) 

否則你使用臨時變量的拷貝構造函數。

(你也可能會解決您移動,構造函數和析構函數,讓你的當前宏)

+0

這似乎沒有什麼區別。但是,如果我刪除了三元操作,只需使用參數LogScopeRAII即可運行。三元組有什麼不對?我確認它正在評估相同的LogScopeRAII - 帶參數的LogScopeRAII - 無論哪種方式,所以這是別的。它不斷地構造和解構,然後再解構一次......這很奇怪,因爲沒有匹配的構造函數可以使用它。不知道這怎麼可能。這裏是我的測試設置的一個pastebin:http://pastebin.com/8mSjVnPN – Stradigos

+0

最終,這是一個MSVC C++ 14的問題,因爲它在GCC中完美工作。我想它不會在GCC中產生副本,但會在MSVC中產生副本。請參閱:http://stackoverflow.com/questions/22078029/why-does-the-ternary-operator-prevent-return-value-optimization和http://stackoverflow.com/questions/11914691/copy-elision-move- constructor-not-called-when-using-ternary-expression-in-retur我在適當的地方添加了static_cast 來修復它。好奇的是,如果有更好的辦法,但問題仍然得到解決。感謝您的幫助。 – Stradigos