有沒有辦法添加或編輯assert引發的消息?我想使用類似在聲明中添加自定義消息?
assert(a == b, "A must be equal to B");
然後,編譯器添加線,時間等等...
這可能嗎?
有沒有辦法添加或編輯assert引發的消息?我想使用類似在聲明中添加自定義消息?
assert(a == b, "A must be equal to B");
然後,編譯器添加線,時間等等...
這可能嗎?
我見過的黑客是使用&&
運營商。由於指針「是真的」,如果它不爲空,你可以做以下不改變的條件:
assert(a == b && "A is not equal to B");
由於assert
顯示失敗,它會顯示你的消息太條件。如果這還不夠,你可以編寫自己的myAssert
函數或宏,它會顯示你想要的。
斷言是宏/功能組合。你可以定義自己的宏/功能,採用__FILE__
,__BASE_FILE__
,__LINE__
等,用自己的函數,它的自定義消息
另一種選擇是扭轉操作數和用逗號。你需要額外的括號以逗號不是參數之間的分隔符處理:
assert(("A must be equal to B", a == b));
(這是從上述意見覆制,爲更好的可視性)
這是一個很好的方法,當使用'-Wunused-value – v010dya 2016-01-30 11:02:57
或用宏編譯時,它會顯示「警告:逗號運算符的左操作數沒有任何效果」,在g ++中編譯時使用#ifndef m_assert #define m_assert(expr,msg)assert((msg,expr)) #endif – 2017-08-03 10:50:29
BOOST_ASSERT_MSG(expre, msg)
http://www.boost.org/doc/libs/1_51_0/libs/utility/assert.html
你可以直接使用它或複製Boost的代碼。另外請注意Boost assert只是頭文件,所以如果你不想安裝所有的Boost,你可以只抓取那個文件。
對於VC,在ASSERT.H添加以下代碼,
#define assert2(_Expression, _Msg) (void)((!!(_Expression)) || (_wassert(_CRT_WIDE(#_Msg), _CRT_WIDE(__FILE__), __LINE__), 0))
修改你的編譯器頭文件是個壞主意。 – 2015-04-21 00:31:40
由於zneak的回答有些卷積碼,更好的方法是僅僅發表評論你在談論的字符串文本。即:
assert(a == b); // A must be equal to B
由於斷言錯誤將查找的文件和行反正從錯誤信息的讀者,他們將在這裏看到完整的解釋。
因爲,在一天結束的時候,這樣的:
assert(number_of_frames != 0); // Has frames to update
讀取比這更好:
assert(number_of_frames != 0 && "Has frames to update");
的代碼,即人類分析的條件。可讀性。也不是一種語言破解。
「由於斷言錯誤的讀者將從錯誤消息中查找文件和行,」 - 只有在他們勤奮的情況下。 – 2017-09-27 04:49:17
只有當他們想修復你的意思是......多麼愚蠢的評論 – metamorphosis 2017-09-27 05:12:41
讓人們看到問題越容易,他們就越有可能採取行動。 – 2017-09-27 15:51:15
爲什麼沒有人提到最乾淨的解決方案?
bool AMustBeEqualToB = (a == b);
assert(AMustBeEqualToB);
如果評估的表達式不能被證明沒有副作用(比如函數調用),那麼這個方法會強制編譯器包含評估,即使在一個發佈版本中,斷言將被忽略。至於「乾淨」 - 代碼看起來最好的是個人喜好,但我懷疑很多人會認爲它比其旁邊的評論更可讀。 – 2015-09-14 00:19:38
但是,如果我們發表評論,斷言失敗後將不會在控制檯上打印。 – 2015-09-14 12:08:53
是的,的確如此,但是 - 正如其他人所指出的那樣 - 如果您斷言失敗,那麼您首先要做的第一件事就是訪問違規代碼行。大多數情況下,除非您查看斷言失敗的上下文,否則您甚至不會知道「a」和「b」的含義,因此無論如何您必須訪問代碼。如果斷言在沒有代碼見解的情況下應該是可以理解的,那麼對於我來說,這將暗示您在這種情況下使用了錯誤的錯誤報告機制。 – 2015-09-15 00:14:16
這裏是我的版本斷言宏,它接受的消息,並以明確的方式打印的所有問題:
#include <iostream>
#ifndef NDEBUG
# define M_Assert(Expr, Msg) \
__M_Assert(#Expr, Expr, __FILE__, __LINE__, Msg)
#else
# define M_Assert(Expr, Msg) ;
#endif
void __M_Assert(const char* expr_str, bool expr, const char* file, int line, const char* msg)
{
if (!expr)
{
std::cerr << "Assert failed:\t" << msg << "\n"
<< "Expected:\t" << expr_str << "\n"
<< "Source:\t\t" << file << ", line " << line << "\n";
abort();
}
}
現在,你可以使用這個
M_Assert(ptr != nullptr, "MyFunction: requires non-null argument");
而如果的失敗你會得到這樣的消息:
斷言失敗:MyFunction的:要求非空參數
預計:PTR = nullptr
來源:C:\ MyProject的\ src.cpp 22行
尼斯和清潔,隨時在您的代碼中使用它=)
不錯的一個。非常有用 – Killrazor 2016-06-03 11:55:21
我有點困惑。 #Expr是否被視爲直接替換的字符串? #Expr和Expr有什麼區別? – 2016-09-22 17:25:30
@MinhTran讓我們假設你的斷言條件是'x == y'。然後Expr將展開爲'if(!(x == y))',這是檢查條件的地方,並且#Expr將展開爲字符串文字'「x == y」',然後我們將其輸入到錯誤消息中。 – 2016-10-14 07:27:57
您可以定義一個宏,如[this](http://stackoverflow.com/a/3767883/1070480)。 – HelloGoodbye 2015-12-18 12:02:39