劉未鵬牛最近的一篇文章“C++11和快速反覆式開發法”中,提到一個小工具Ensure,很有用,但他不方便提供具體代碼,這裡我給出一個簡易實現。
Ensure用法如:
ENSURE(0 <= index && index < v.size())(index)(v.size());
宣告失敗時,會列印:
Failed: 0 <= index && index < v.size()File: xxx.cpp Line: 123Context Variables: index = 12345 v.size() = 100
概括來說,Ensure至少包括以下特性:
1) 不區分debug和release,始終生效。
2) 宣告失敗時,列印運算式,同assert。
3) 列印檔案和行號。
4) 可以追加無限個()來捕獲上下文中運算式的文本和值。
另外,可以選擇拋出異常,對於沒有被捕獲的異常,在windows下產生mindump。
我的簡易版:
#include <exception>#include <sstream>class EnsureException: public std::exception{public: EnsureException(const char *exp, const char *file, int line) { std::ostringstream so; so << "ensure failed : " << exp << '\n'; so << file << '(' << line << ')' << '\n'; so << "context variables:\n"; m_what = so.str(); } ~EnsureException() throw (){} template<typename T> EnsureException& operator << (const std::pair<const char *, T>& p) { std::ostringstream so; so << '\t' << p.first << " : " << p.second << '\n'; m_what += so.str(); return *this; } EnsureException& operator << (int){ return *this; } const char *what() const throw () { return m_what.c_str(); }private: mutable std::string m_what;};static int A = 0, B = 0;#define AB(a, N) std::make_pair(#a, a) << N#define A(a) AB(a, B)#define B(a) AB(a, A)#define ENSURE(b) if (b); else throw EnsureException(#b, __FILE__, __LINE__) << Aint main(){ try { int a = 2, b = 3; ENSURE(a > 1); ENSURE(a > 1)(a); ENSURE(a > 2 && b <= 3)(a)(b)(5); } catch (const EnsureException& e) { cout << "catch exception:\n" << e.what() << endl; }}