

最過度設計的C ++斷言庫
圖書館理念:提供盡可能多的有用的診斷信息。
圖書館所做的一些很棒的事情:
void zoog ( const std::map<std::string, int >& map) {
DEBUG_ASSERT (map. contains ( " foo " ), " expected key not found " , map);
}
ASSERT (vec.size() > min_items(), "vector doesn't have enough items", vec);
std::optional< float > get_param ();
float f = * ASSERT_VAL (get_param());
斷言的類型:
有條件的斷言:
DEBUG_ASSERT :在調試中檢查,但在發行版中沒有任何作用(類似於標準庫的assert )ASSERT :在調試和發布中檢查ASSUME :在調試中檢查並用作發行版的優化提示無條件斷言:
PANIC :在調試和釋放中觸發UNREACHABLE :在調試中觸發,在發行中被標記為無法達到更喜歡Lowecase assert ?
您可以使用-DLIBASSERT_LOWERCASE啟用小寫debug_assert並assert別名。
特徵摘要:
ASSERT_EQ等)的斷言表達式的自動分解DEBUG_ASSERT_VAL和ASSERT_VAL變體返回一個值,以便可以將它們無縫集成到代碼中,例如FILE* f = ASSERT_VAL(fopen(path, "r") != nullptr) include (FetchContent)
FetchContent_Declare(
libassert
GIT_REPOSITORY https://github.com/jeremy-rifkin/libassert.git
GIT_TAG v2.1.2 # <HASH or TAG>
)
FetchContent_MakeAvailable(libassert)
target_link_libraries (your_target libassert::assert)
# On windows copy libassert.dll to the same directory as the executable for your_target
if ( WIN32 )
add_custom_command (
TARGET your_target POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:libassert::assert>
$<TARGET_FILE_DIR:your_target>
)
endif ()請確保使用-DCMAKE_BUILD_TYPE=Debug或-DDCMAKE_BUILD_TYPE=RelWithDebInfo進行符號和行信息。
在MacOS上,建議生成.DSYM文件,請參見下面的平台物流。
有關使用庫的其他方法,例如通過軟件包管理人員或系統範圍的安裝,請參見下面的用法。
從根本上說,斷言的作用是驗證軟件中的假設並確定違反其來源的違規行為。斷言工具應優先為開發人員提供盡可能多的信息和上下文,以允許快速分類。不幸的是,現有的語言和圖書館工具提供了非常有限的分類信息。
例如,用stdlib斷言一個assert(n <= 12);關於失敗的原因,沒有提供有關其失敗或導致失敗的原因的信息。提供堆棧痕跡和n Greatley的價值改善了分類和調試。理想情況下,斷言失敗應提供足夠的診斷信息,使程序員不必重新運行調試器來查明問題。
該庫的版本1是一項探索,研究了可以將多少有用的信息和功能包裝到主張中,同時還為開發人員提供了快速簡便的界面。
該庫的版本2從版本1中汲取了教訓,以創建一個我個人發現開發必不可少的工具。
該庫支持的最重要功能是自動表達分解。無需ASSERT_LT或其他此類麻煩, assert(vec.size() > 10);如上所述,自動理解。
顯示斷言表達式所涉及的值。避免了冗餘診斷,例如2 => 2 。
DEBUG_ASSERT (map.count( 1 ) == 2);
只能從宏調用中提取完整的斷言表達式。表明表達式的哪些部分對應於哪些值需要一些基本的表達式解析。 C ++語法是模棱兩可的,但大多數表達式可能會被歧義。
該庫中的所有斷言都支持可選的診斷消息以及任意其他診斷消息。
FILE* f = ASSERT_VAL(fopen(path, " r " ) != nullptr , " Internal error with foobars " , errno, path);為errno提供了特殊的處理,並自動調用Strerror。
注意:僅在斷言的失敗路徑中評估額外的診斷。

已經為生成漂亮的堆棧痕跡並儘可能地格式化了很多工作。 cpptrace用作stacktraces Pre-c ++ 23的便攜式和獨立的解決方案。可選配置可以在庫的文檔中找到。
值得注意的一項功能是,只有打印了區分路徑所需的最小目錄,而不是總是打印完整的路徑。

值得指出的另一個功能是,堆棧跟踪將折疊帶有深層遞歸的軌跡:

主張處理程序在適當的地方應用語法突出顯示,如上所述所有屏幕截圖所示。這是為了提高可讀性。
Libassert支持自定義斷言失敗處理程序:
void handler (assert_type type, const assertion_info& assertion) {
throw std::runtime_error ( " Assertion failed: n " + assertion. to_string ());
}
int main () {
libassert::set_failure_handler (handler);
}盡可能有效地產生值的調試弦樂:字符串,字符,數字應按照您的期望打印。此外,容器,元組,std ::可選,智能指針等都被串制以顯示盡可能多的信息。如果用戶定義的類型Overloads operator<<(std::ostream& o, const S& s) ,該超載將被調用。否則將打印默認消息。此外,還提供了一個弦定定制點:
template <> struct libassert ::stringifier<MyObject> {
std::string stringify ( const MyObject& type) {
return ...;
}
};

如果在斷言表達的兩側使用十六進制/二進制,則在十六進製或二進制中打印斷言值:
ASSERT (get_mask() == 0b00001101);
由於表達式已經自動分解,因此您可以選擇使用符號安全進行簽名的無分配比較,並使用-DLIBASSERT_SAFE_COMPARISONS :
ASSERT ( 18446744073709551606ULL == - 10 );
libassert提供兩個標題<libassert/assert-catch2.hpp>和<libassert/assert-gtest.hpp>可與catch2和googletest一起使用。
GTEST的示例輸出:

下面的更多信息。
Libassert提供了三種類型的斷言,每種斷言都略有不同,具體取決於應檢查何時以及如何解釋:
| 姓名 | 影響 |
|---|---|
DEBUG_ASSERT | 在調試中檢查,發行中沒有密碼 |
ASSERT | 檢查兩個調試和發布版本 |
ASSUME | 在調試中檢查, if(!(expr)) { __builtin_unreachable(); }在版本中 |
無條件斷言
| 姓名 | 影響 |
|---|---|
PANIC | 在調試和釋放中觸發 |
UNREACHABLE | 在調試中觸發,在發行中標記為無法到達。 |
對PANIC和UNREACHABLE ASSERT(false, ...)的好處是,編譯器獲取[[noreturn]]信息。
ASSUME故障路徑標記為無法到達的發行中,並可能向優化器提供有用的信息。這並不是所有斷言的默認行為,因為這樣做的直接後果是-DNDEBUG中的斷言失敗可以導致UB,最好使這一明確的效果。
可以在表達式中使用的斷言變體,例如FILE* file = ASSERT_VAL(fopen(path, "r"), "Failed to open file"); ,也可用:
| 姓名 | 影響 |
|---|---|
DEBUG_ASSERT_VAL | 在調試中進行檢查,必須在調試和發布中進行評估 |
ASSERT_VAl | 檢查兩個調試和發布版本 |
ASSUME_VAL | 在調試中檢查, if(!(expr)) { __builtin_unreachable(); }在版本中 |
注意:與DEBUG_ASSERT不同,即使在發行版中,仍必須評估DEBUG_ASSERT_VAL的表達式。當然,如果結果未使用並且沒有產生任何副作用,它將被優化。
性能:就運行時性能而言,在-Og或更高的情況下,對呼叫的影響非常小。代碼中的快速路徑(即斷言不會失敗的地方)會很快。一旦發生斷言失敗,需要進行大量工作。但是,由於失敗應該很少見,所以這無關緊要。
編譯速度: ,與此庫魔術所需的所有模板實例相關聯的編譯時間成本。
其他:
筆記
由於表達分解, ASSERT(1 = 2);編譯。
所有斷言功能都是宏。以下是一些與它們接口的偽刪除:
void DEBUG_ASSERT (expression, [optional message], [optional extra diagnostics, ...]);
void ASSERT (expression, [optional message], [optional extra diagnostics, ...]);
void ASSUME (expression, [optional message], [optional extra diagnostics, ...]);
decltype ( auto ) DEBUG_ASSERT_VAL(expression, [optional message], [optional extra diagnostics, ...]);
decltype ( auto ) ASSERT_VAL (expression, [optional message], [optional extra diagnostics, ...]);
decltype ( auto ) ASSUME_VAL (expression, [optional message], [optional extra diagnostics, ...]);
void PANIC ([optional message], [optional extra diagnostics, ...]);
void UNREACHABLE ([optional message], [optional extra diagnostics, ...]); -DLIBASSERT_PREFIX_ASSERTIONS可用於將這些宏與LIBASSERT_一起添加。這對於包裝Libassert斷言很有用。
-DLIBASSERT_LOWERCASE可用於啟用debug_assert並assert DEBUG_ASSERT和ASSERT的別名。請參閱:更換<Cassert>。
expression該expression自動分解,因此可以提供診斷信息。所得類型必須可轉換為布爾值。
表達樹中頂級操作的左側和右側之間的操作由功能對象評估。
注意:布爾邏輯運算符( && and || )由於短路短而被默認分解。
assertion message可以提供可選的斷言消息。如果斷言表達式之後的第一個參數或恐慌/無法到達中的第一個參數是任何字符串類型,它將用作消息(如果您希望第一個參數(恰好是字符串)是一個額外的診斷值,而是首先傳遞一個空字符串,則首先傳遞一個空ASSERT(foo, "", str);
注意:斷言信息表達僅在斷言的失敗路徑中評估。
extra diagnostics可以提供任意數量的額外診斷值。如果檢查失敗,則這些顯示在表達式診斷下方。
注意:僅在斷言的失敗路徑中評估額外的診斷。
提供errno時會有特殊的處理:自動顯示strerror的值。
為了促進易於集成到代碼_VAL變體中,從斷言表達式返回值。返回的值確定如下:
ASSERT_VAL(foo());或在斷言表達式中ASSERT_VAL(false); ),則表達式的值只是返回。== , != , < , <= , > , >= , && , || ,或任何分配或複合分配,然後返回左手操作數的值。& | , ^ , << , >>或任何具有優先級的二進制運算符,然後返回整個表達式的值。即, ASSERT_VAL(foo() > 2);返回foo()和ASSERT_VAL(x & y);返回x & y的計算結果;
如果從選擇返回的斷言表達式中的值是LVALUE,則斷言調用的類型將是LVALUE參考。如果從斷言表達式的值是rvalue,則調用的類型將是rvalue。
namespace libassert {
[[nodiscard]] std::string stacktrace (
int width = 0 ,
const color_scheme& scheme = get_color_scheme(),
std::size_t skip = 0
);
template < typename T> [[nodiscard]] std::string_view type_name () noexcept ;
template < typename T> [[nodiscard]] std::string pretty_type_name () noexcept ;
template < typename T> [[nodiscard]] std::string stringify ( const T& value);
}stacktrace :生成堆棧跟踪,格式為給定寬度(0,無寬度格式)type_name :返回t的類型名稱pretty_type_name :返回Tstringify :產生值的調試弦樂化 namespace libassert {
void enable_virtual_terminal_processing_if_needed ();
inline constexpr int stdin_fileno = 0 ;
inline constexpr int stdout_fileno = 1 ;
inline constexpr int stderr_fileno = 2 ;
bool isatty ( int fd);
[[nodiscard]] int terminal_width ( int fd);
}enable_virtual_terminal_processing_if_needed :啟用Windows終端的ANSI逃生序列,顏色輸出需要。isatty :如果文件描述符對應於終端,則返回trueterminal_width :返回由fd代表的終端的寬度或錯誤 namespace libassert {
// NOTE: string view underlying data should have static storage duration, or otherwise live as
// long as the scheme is in use
struct color_scheme {
std::string_view string, escape, keyword, named_literal, number, punctuation, operator_token,
call_identifier, scope_resolution_identifier, identifier, accent, unknown, reset;
static const color_scheme ansi_basic;
static const color_scheme ansi_rgb;
static const color_scheme blank;
};
void set_color_scheme ( const color_scheme&);
const color_scheme& get_color_scheme ();
}默認情況下,使用color_scheme::ansi_rgb 。要禁用顏色,請使用color_scheme::blank 。
set_color_scheme :在stderr為終端時設置默認斷言處理程序的配色方案 namespace libassert {
void set_separator (std::string_view separator);
}set_separator :在斷言診斷輸出中的表達式和值之間設置分離器。默認值: => 。注意:不螺紋安全。 namespace libassert {
enum class literal_format_mode {
infer, // infer literal formats based on the assertion condition
no_variations, // don't do any literal format variations, just default
fixed_variations // always use a fixed set of formats (in addition to the default format)
};
void set_literal_format_mode (literal_format_mode);
enum class literal_format : unsigned {
// integers and floats are decimal by default, chars are of course chars, and everything
// else only has one format that makes sense
default_format = 0 ,
integer_hex = 1 ,
integer_octal = 2 ,
integer_binary = 4 ,
integer_character = 8 , // format integers as characters and characters as integers
float_hex = 16 ,
};
[[nodiscard]] constexpr literal_format operator |(literal_format a, literal_format b);
void set_fixed_literal_format (literal_format);
}set_literal_format_mode :設置庫是否應顯示字面變化或推斷它們set_fixed_literal_format :設置固定的文字格式配置,會自動更改literal_format_mode;請注意,默認格式將始終與其他格式一起使用 namespace libassert {
enum class path_mode {
full, // full path is used
disambiguated, // only enough folders needed to disambiguate are provided
basename, // only the file name is used
};
LIBASSERT_EXPORT void set_path_mode (path_mode mode);
}set_path_mode :設置斷言輸出的路徑縮短模式。默認值: path_mode::disambiguated 。 namespace libassert {
enum class assert_type {
debug_assertion,
assertion,
assumption,
panic,
unreachable
};
struct LIBASSERT_EXPORT binary_diagnostics_descriptor {
std::string left_expression;
std::string right_expression;
std::string left_stringification;
std::string right_stringification;
};
struct extra_diagnostic {
std::string_view expression;
std::string stringification;
};
struct LIBASSERT_EXPORT assertion_info {
std::string_view macro_name;
assert_type type;
std::string_view expression_string;
std::string_view file_name;
std:: uint32_t line;
std::string_view function;
std::optional<std::string> message;
std::optional<binary_diagnostics_descriptor> binary_diagnostics;
std::vector<extra_diagnostic> extra_diagnostics;
size_t n_args;
std::string_view action () const ;
const cpptrace::raw_trace& get_raw_trace () const ;
const cpptrace::stacktrace& get_stacktrace () const ;
[[nodiscard]] std::string header ( int width = 0 , const color_scheme& scheme = get_color_scheme()) const ;
[[nodiscard]] std::string tagline ( const color_scheme& scheme = get_color_scheme()) const ;
[[nodiscard]] std::string location () const ;
[[nodiscard]] std::string statement ( const color_scheme& scheme = get_color_scheme()) const ;
[[nodiscard]] std::string print_binary_diagnostics ( int width = 0 , const color_scheme& scheme = get_color_scheme()) const ;
[[nodiscard]] std::string print_extra_diagnostics ( int width = 0 , const color_scheme& scheme = get_color_scheme()) const ;
[[nodiscard]] std::string print_stacktrace ( int width = 0 , const color_scheme& scheme = get_color_scheme()) const ;
[[nodiscard]] std::string to_string ( int width = 0 , const color_scheme& scheme = get_color_scheme()) const ;
};
} Debug Assertion failed at demo.cpp:194: void foo::baz(): Internal error with foobars
debug_assert(open(path, 0) >= 0, ...);
Where:
open(path, 0) => -1
Extra diagnostics:
errno => 2 "No such file or directory"
path => "/home/foobar/baz"
Stack trace:
#1 demo.cpp:194 foo::baz()
#2 demo.cpp:172 void foo::bar<int>(std::pair<int, int>)
#3 demo.cpp:396 main
Debug Assertion failed : assertion_info.action()demo.cpp:194 : assertion_info.file_name and assertion_info.linevoid foo::baz() : assertion_info.pretty_functionInternal error with foobars : assertion_info.messagedebug_assert : assertion_info.macro_nameopen(path, 0) >= 0 : assertion_info.expression_string... :由assertion_info.n_args確定,該論點總數傳遞給了主張宏open(path, 0) : assertion_info.binary_diagnostics.left_expression-1 : assertion_info.binary_diagnostics.left_stringification0 => 0沒有用)errno : assertion_info.extra_diagnostics[0].expression2 "No such file or directory" : assertion_info.extra_diagnostics[0].stringificationassertion_info.get_stacktrace()或assertion_info.get_raw_trace()獲取跟踪而無需解決跟踪幫助者:
assertion_info.header() :
Debug Assertion failed at demo.cpp:194: void foo::baz(): Internal error with foobars
debug_assert(open(path, 0) >= 0, ...);
Where:
open(path, 0) => -1
Extra diagnostics:
errno => 2 "No such file or directory"
path => "/home/foobar/baz"
assertion_info.tagline() :
Debug Assertion failed at demo.cpp:194: void foo::baz(): Internal error with foobars
assertion_info.location() :
筆記
路徑處理將根據路徑模式進行
demo.cpp:194
assertion_info.statement() :
debug_assert(open(path, 0) >= 0, ...);
assertion_info.print_binary_diagnostics() :
Where:
open(path, 0) => -1
assertion_info.print_extra_diagnostics() :
Extra diagnostics:
errno => 2 "No such file or directory"
path => "/home/foobar/baz"
assertion_info.print_stacktrace() :
Stack trace:
#1 demo.cpp:194 foo::baz()
#2 demo.cpp:172 void foo::bar<int>(std::pair<int, int>)
#3 demo.cpp:396 main
Libassert為用戶定義類型提供了自定義點:
template <> struct libassert ::stringifier<MyObject> {
std::string stringify ( const MyObject& type) {
return ...;
}
};默認情況下,任何類似容器的用戶定義類型都將自動串起。
此外, LIBASSERT_USE_FMT可用於允許Libassert使用fmt::formatter s。
最後,可以將帶有Ostream operator<< Overload的任何類型串起。
namespace libassert {
void set_failure_handler ( void (*handler)( const assertion_info&));
}set_failure_handler :設置程序的斷言處理程序。一個示例主張處理程序類似於默認處理程序:
void libassert_default_failure_handler ( const assertion_info& info) {
libassert::enable_virtual_terminal_processing_if_needed (); // for terminal colors on windows
std::string message = info. to_string (
libassert::terminal_width (libassert::stderr_fileno),
libassert::isatty (libassert::stderr_fileno)
? libassert::get_color_scheme ()
: libassert::color_scheme::blank
);
std::cerr << message << std::endl;
switch (info. type ) {
case libassert::assert_type::assertion:
case libassert::assert_type::debug_assertion:
case libassert::assert_type::assumption:
case libassert::assert_type::panic:
case libassert::assert_type::unreachable:
( void ) fflush (stderr);
std::abort ();
// Breaking here as debug CRT allows aborts to be ignored, if someone wants to make a
// debug build of this library
break ;
default :
std::cerr << " Critical error: Unknown libassert::assert_type " << std::endl;
std::abort ( 1 );
}
}默認情況下,Libassert從所有斷言類型中刪除。但是,可能希望從某些或所有斷言類型中提出一個例外,而不是流產。
重要的
故障處理程序不得返回assert_type::panic and assert_type::unreachable 。
Libassert支持關於斷言未能使主張在斷言線上闖入辯論的問題的程序斷點,而不是在呼叫階段深處的幾層:

此功能當前選擇加入,可以通過定義LIBASSERT_BREAK_ON_FAIL啟用它。最好作為編譯器標誌完成: -DLIBASSERT_BREAK_ON_FAIL或/DLIBASSERT_BREAK_ON_FAIL 。
在內部,圖書館在執行指令以斷開調試器之前檢查了調試器的主題。默認情況下,該檢查僅在第一個斷言失敗中執行一次。在某些情況下,可能需要配置此檢查以始終執行,例如,如果您使用的是一個自定義主張處理程序,該處理程序會引發異常而不是中止,並且您可能可以從斷言失敗中恢復,以稍後允許額外的失敗,並且您只能通過程序運行來附加辯論者。您可以使用libassert::set_debugger_check_mode來控制此檢查的執行方式:
namespace libassert {
enum class debugger_check_mode {
check_once,
check_every_time,
};
void set_debugger_check_mode (debugger_check_mode mode) noexcept ;
}該庫還公開其內部實用程序,以設置斷點並檢查該程序是否被調試:
namespace libassert {
bool is_debugger_present () noexcept ;
}
# define LIBASSERT_BREAKPOINT () <...internals...>
# define LIBASSERT_BREAKPOINT_IF_DEBUGGING () <...internals...>此API模擬了P2514的API,該API已被C ++ 26接受。
關於constexpr的註釋:對於Clang和MSVC Libassert可以使用編譯器內在,但是,對於GCC內聯裝配,需要使用編譯器。 constexpr函數前C ++ 20中不允許內聯彙編20,但是,GCC在GCC 10之後通過警告支持它,並且圖書館可以警告GCC 12。
定義:
LIBASSERT_USE_MAGIC_ENUM :使用魔術枚舉來弦樂枚舉值LIBASSERT_DECOMPOSE_BINARY_LOGICAL :分解&&和||LIBASSERT_SAFE_COMPARISONS :啟用分解表達式的安全簽名未分配的比較LIBASSERT_PREFIX_ASSERTIONS :前綴所有主張宏與LIBASSERT_LIBASSERT_USE_FMT :啟用libfmt集成LIBASSERT_NO_STRINGIFY_SMART_POINTER_OBJECTS :禁用智能指針內容的字符串Cmake:
LIBASSERT_USE_EXTERNAL_CPPTRACE :使用externam cpptrace而不是用fetchContent啟動庫LIBASSERT_USE_EXTERNAL_MAGIC_ENUM :使用外部魔術枚舉而不是用fitchcontent庫存筆記
由於MSVC的不合格預處理器,沒有簡單的方法來提供斷言包裝器。為了使用測試庫集成/Zc:preprocessor 。
libassert在libassert/assert-catch2.hpp中提供了catch2集成:
# include < libassert/assert-catch2.hpp >
TEST_CASE ( " 1 + 1 is 2 " ) {
ASSERT ( 1 + 1 == 3 );
}
目前,提供的唯一宏是ASSERT ,它將在內部執行REQUIRE 。
注意:v3.6.0 ANSI顏色代碼在干擾Catch2的線條包裝之前,因此在較舊版本上禁用了顏色。
libassert在libassert/assert-gtest.hpp中提供了gtest集成:
# include < libassert/assert-gtest.hpp >
TEST (Addition, Arithmetic) {
ASSERT ( 1 + 1 == 3 );
}
目前,Libassert提供了ASSERT ,並EXPECT GTEST宏。
但是,這並不像我想要的那樣漂亮,但是它可以完成工作。
該庫的目標> = = C ++ 17,並支持所有主要編譯器和所有主要平台(Linux,MacOS,Windows和Mingw)。
注意:該庫確實依賴於某些編譯器擴展程序和編譯器特定功能,因此它與-pedantic不兼容。
與Cmake提取:
include (FetchContent)
FetchContent_Declare(
libassert
GIT_REPOSITORY https://github.com/jeremy-rifkin/libassert.git
GIT_TAG v2.1.2 # <HASH or TAG>
)
FetchContent_MakeAvailable(libassert)
target_link_libraries (your_target libassert::assert)注意:在Windows和MacOS上,建議一些額外的工作,請參見下面的平台物流。
請確保使用-DCMAKE_BUILD_TYPE=Debug或-DDCMAKE_BUILD_TYPE=RelWithDebInfo進行符號和行信息。
git clone https://github.com/jeremy-rifkin/libassert.git
git checkout v2.1.2
mkdir libassert/build
cd libassert/build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j
sudo make install通過CMAKE:
find_package (libassert REQUIRED)
target_link_libraries (<your target > libassert::assert)請確保使用-DCMAKE_BUILD_TYPE=Debug或-DDCMAKE_BUILD_TYPE=RelWithDebInfo進行符號和行信息。
或用-lassert編譯:
g++ main.cpp -o main -g -Wall -lassert
./main如果您沿著錯誤
error while loading shared libraries: libassert.so: cannot open shared object file: No such file or directory
您可能必須運行sudo /sbin/ldconfig才能創建任何必要的鏈接並更新緩存,以便系統可以找到libcpptrace.so(我必須在ubuntu上這樣做)。僅在整個系統範圍內安裝時。通常,您的軟件包經理在安裝新庫時為您做到這一點。
git clone https: // github.com / jeremy - rifkin / libassert.git
git checkout v2. 1.2
mkdir libassert / build
cd libassert / build
cmake . . - DCMAKE_BUILD_TYPE = Release
msbuild libassert.sln
msbuild INSTALL.vcxproj注意:您需要在開發人員PowerShell中作為管理員運行,或使用Visual Studio分發的VCVARSALL.BAT來獲取正確的環境變量設置。
僅適用於本地用戶(或任何自定義前綴):
git clone https://github.com/jeremy-rifkin/libassert.git
git checkout v2.1.2
mkdir libassert/build
cd libassert/build
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX= $HOME /wherever
make -j
sudo make install通過CMAKE:
find_package (libassert REQUIRED PATHS $ENV{HOME} /wherever)
target_link_libraries (<your target > libassert::assert)手動使用:
g++ main.cpp -o main -g -Wall -I$HOME/wherever/include -L$HOME/wherever/lib -lassert
首先使用CMAKE的庫,請首先按照系統範圍的安裝,本地用戶安裝或軟件包管理器進行安裝說明。
使用以下參數與libassert進行編譯:
| 編譯器 | 平台 | 依賴性 |
|---|---|---|
| GCC,Clang,Intel,等。 | Linux/MacOS/UNIX | -libassert -I[path] [cpptrace args] |
| 明格 | 視窗 | -libassert -I[path] [cpptrace args] |
| MSVC | 視窗 | assert.lib /I[path] [cpptrace args] |
| 鐺 | 視窗 | -libassert -I[path] [cpptrace args] |
對於-I[path]和/I[path]中的[path]路徑]佔位符,指定包含libassert/assert.hpp文件夾的路徑。
如果要靜態鏈接,則還需要指定-DLIBASSERT_STATIC_DEFINE 。
對於[cpptrace args]佔位符,請參閱CPPTRACE文檔。
Libassert可通過conan https://conan.io/center/recipes/libassert獲得。
[requires]
libassert/2.1.2
[generators]
CMakeDeps
CMakeToolchain
[layout]
cmake_layout
# ...
find_package (libassert REQUIRED)
# ...
target_link_libraries (YOUR_TARGET libassert::assert) vcpkg install libassert
find_package (libassert CONFIG REQUIRED)
target_link_libraries (YOUR_TARGET PRIVATE libassert::assert)Windows和Macos需要一些額外的工作才能使所有內容都在正確的位置
在Windows上複製庫.dll:
# Copy the assert.dll on windows to the same directory as the executable for your_target.
# Not required if static linking.
if ( WIN32 )
add_custom_command (
TARGET your_target POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:libassert::assert>
$<TARGET_FILE_DIR:your_target>
)
endif ()在MacOS上,建議生成一個包含您程序的調試信息的DSYM文件:
在Xcode cmake中,這可以完成
set_target_properties (your_target PROPERTIES XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "dwarf-with-dsym" )外部XCode可以使用dsymutil yourbinary完成:
# Create a .dSYM file on macos. Currently required, but hopefully not for long
if ( APPLE )
add_custom_command (
TARGET your_target
POST_BUILD
COMMAND dsymutil $<TARGET_FILE:your_target>
)
endif ()該庫不是<cassert>的替換。 -DLIBASSERT_LOWERCASE可用於為斷言宏創建小寫別名,但請注意,Libassert的ASSERT仍在釋放中檢查。要替換<cassert>用libassert使用,請用DEBUG_ASSERT替換assert或沿著以下幾行創建一個別名:
# define assert (...) DEBUG_ASSERT(__VA_ARGS__)要注意的一件事是:從技術上講,標準不允許使用Cassert的assert ,但這對於任何理智的編譯器來說都不是一個問題。
不,還沒有。
cpp-sort即使使用諸如assert_eq之類的結構,也經常缺乏斷言診斷。例如,在生鏽中顯示左右值,但不顯示表達式本身:
fn main ( ) {
let count = 4 ;
assert_eq ! ( count , 2 ) ;
} thread 'main' panicked at 'assertion failed: `(left == right)`
left: `4`,
right: `2`', /app/example.rs:3:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
這沒有可能的幫助。
功能其他語言 /其標準庫提供:
| C/C ++ | 銹 | C# | 爪哇 | Python | JavaScript | libassert | |
|---|---|---|---|---|---|---|---|
| 表達式字符串 | ✔️ | ✔️ | |||||
| 地點 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| 堆棧跟踪 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | |
| 斷言消息 | ** | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| 額外的診斷 | * | * | * | * | ✔️ | ||
| 二進制專業 | ✔️ | ✔️ | ✔️ | ||||
| 自動表達分解 | ✔️ | ||||||
| 亞表達字符串 | ✔️ |
* :通過字符串格式進行,但這是亞理想的。
** : assert(expression && "message")通常使用,但這是亞理想的,僅允許字符串文字消息。
Extras:
| C/C ++ | 銹 | C# | 爪哇 | Python | JavaScript | libassert | |
|---|---|---|---|---|---|---|---|
| 語法突出顯示 | ? | ✔️ | |||||
| 字面格式的一致性 | ✔️ | ||||||
| 表達字符串和表達值無處不在 | ✔️ | ||||||
| 從斷言中返回值,以允許斷言被整合到表達式中 | ✔️ |