2010-09-11 33 views
88

有沒有辦法添加或編輯assert引發的消息?我想使用類似在聲明中添加自定義消息?

assert(a == b, "A must be equal to B"); 

然後,編譯器添加時間等等...

這可能嗎?

+0

您可以定義一個宏,如[this](http://stackoverflow.com/a/3767883/1070480)。 – HelloGoodbye 2015-12-18 12:02:39

回答

169

我見過的黑客是使用&&運營商。由於指針「是真的」,如果它不爲空,你可以做以下不改變的條件:

assert(a == b && "A is not equal to B"); 

由於assert顯示失​​敗,它會顯示你的消息太條件。如果這還不夠,你可以編寫自己的myAssert函數或宏,它會顯示你想要的。

+4

Jaja!精美的一段代碼。真的有用!謝謝! – Killrazor 2010-09-11 23:18:29

+1

@Killrazor如果解決了您的問題,請考慮通過點擊旁邊的複選標記將答案標記爲「接受」。 :) – zneak 2010-09-11 23:21:30

+15

另一種選擇是顛倒操作數並使用逗號運算符。你需要額外的括號,所以逗號不會被當作參數之間的分隔符:'assert((「A must be equal to B」,a == b));' – 2012-01-08 06:16:52

1

斷言是宏/功能組合。你可以定義自己的宏/功能,採用__FILE____BASE_FILE____LINE__等,用自己的函數,它的自定義消息

21

另一種選擇是扭轉操作數和用逗號。你需要額外的括號以逗號不是參數之間的分隔符處理:

assert(("A must be equal to B", a == b)); 

(這是從上述意見覆制,爲更好的可視性)

+1

這是一個很好的方法,當使用'-Wunused-value – v010dya 2016-01-30 11:02:57

+0

或用宏編譯時,它會顯示「警告:逗號運算符的左操作數沒有任何效果」,在g ++中編譯時使用#ifndef m_assert #define m_assert(expr,msg)assert((msg,expr)) #endif – 2017-08-03 10:50:29

15
BOOST_ASSERT_MSG(expre, msg) 

http://www.boost.org/doc/libs/1_51_0/libs/utility/assert.html

你可以直接使用它或複製Boost的代碼。另外請注意Boost assert只是頭文件,所以如果你不想安裝所有的Boost,你可以只抓取那個文件。

+0

note boost需要你實現assert接口。 – Jichao 2013-10-29 04:54:57

+0

@Jichao,通過實現assert接口是什麼意思? – Tarc 2016-08-22 21:57:04

-4

對於VC,在ASSERT.H添加以下代碼,

#define assert2(_Expression, _Msg) (void)((!!(_Expression)) || (_wassert(_CRT_WIDE(#_Msg), _CRT_WIDE(__FILE__), __LINE__), 0)) 
+8

修改你的編譯器頭文件是個壞主意。 – 2015-04-21 00:31:40

8

由於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"); 

的代碼,即人類分析的條件。可讀性。也不是一種語言破解。

+0

「由於斷言錯誤的讀者將從錯誤消息中查找文件和行,」 - 只有在他們勤奮的情況下。 – 2017-09-27 04:49:17

+0

只有當他們想修復你的意思是......多麼愚蠢的評論 – metamorphosis 2017-09-27 05:12:41

+0

讓人們看到問題越容易,他們就越有可能採取行動。 – 2017-09-27 15:51:15

0

爲什麼沒有人提到最乾淨的解決方案?

bool AMustBeEqualToB = (a == b); 
assert(AMustBeEqualToB); 
+5

如果評估的表達式不能被證明沒有副作用(比如函數調用),那麼這個方法會強制編譯器包含評估,即使在一個發佈版本中,斷言將被忽略。至於「乾淨」 - 代碼看起來最好的是個人喜好,但我懷疑很多人會認爲它比其旁邊的評論更可讀。 – 2015-09-14 00:19:38

+0

但是,如果我們發表評論,斷言失敗後將不會在控制檯上打印。 – 2015-09-14 12:08:53

+0

是的,的確如此,但是 - 正如其他人所指出的那樣 - 如果您斷言失敗,那麼您首先要做的第一件事就是訪問違規代碼行。大多數情況下,除非您查看斷言失敗的上下文,否則您甚至不會知道「a」和「b」的含義,因此無論如何您必須訪問代碼。如果斷言在沒有代碼見解的情況下應該是可以理解的,那麼對於我來說,這將暗示您在這種情況下使用了錯誤的錯誤報告機制。 – 2015-09-15 00:14:16

9

這裏是我的版本斷言宏,它接受的消息,並以明確的方式打印的所有問題:

#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行

尼斯和清潔,隨時在您的代碼中使用它=)

+0

不錯的一個。非常有用 – Killrazor 2016-06-03 11:55:21

+0

我有點困惑。 #Expr是否被視爲直接替換的字符串? #Expr和Expr有什麼區別? – 2016-09-22 17:25:30

+0

@MinhTran讓我們假設你的斷言條件是'x == y'。然後Expr將展開爲'if(!(x == y))',這是檢查條件的地方,並且#Expr將展開爲字符串文字'「x == y」',然後我們將其輸入到錯誤消息中。 – 2016-10-14 07:27:57

相關問題