Baike.dev
All toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
L

libassert

> 编程语言
Open source

The most over-engineered C++ assertion library

722 stars0 likes0 views
WebsiteGitHub

About

The most over-engineered C++ assertion library

libassert

-Community%20Discord-blue?labelColor=2C3239&color=7289DA&style=flat&logo=discord&logoColor=959DA5)

The most over-engineered C++ assertion library

Table of Contents:

  • 30-Second Overview
    • CMake FetchContent Usage
  • Philosophy
  • Features
  • Methodology
  • Considerations
  • In-Depth Library Documentation
    • Library headers
    • Assertion Macros
      • Parameters
      • Return value
    • General Utilities
    • Terminal Utilities
    • Configuration
    • Assertion information
      • Anatomy of Assertion Information
    • Stringification of Custom Objects
    • Custom Failure Handlers
    • Breakpoints
    • Other Configurations
    • Library Version
  • Integration with Test Libraries
    • Catch2
    • GoogleTest
  • ABI Versioning
  • Usage
    • CMake FetchContent
    • System-Wide Installation
    • Local User Installation
    • Use Without CMake
    • Package Managers
      • Conan
      • Vcpkg
    • C++20 Modules
  • Platform Logistics
  • [Replacing ](#replacing-cassert)
  • FAQ
  • Cool projects using libassert
  • Comparison With Other Languages

30-Second Overview

Library philosophy: Provide as much helpful diagnostic info as possible.

Some of the awesome things the library does:

#include 
void zoog(const std::map& 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 get_param();
float f = *ASSERT_VAL(get_param());

Types of assertions:

Conditional assertions:

  • DEBUG_ASSERT: Checked in debug but does nothing in release (analogous to the standard library's assert)
  • ASSERT: Checked in both debug and release
  • ASSUME: Checked in debug and serves as an optimization hint in release

Unconditional assertions:

  • PANIC: Triggers in both debug and release
  • UNREACHABLE: Triggers in debug, marked as unreachable in release

Prefer lowecase assert?

You can enable the lowercase debug_assert and assert aliases with -DLIBASSERT_LOWERCASE.

Summary of features:

  • Automatic decomposition of assertion expressions without macros such as ASSERT_EQ etc.
  • Assertion messages
  • Arbitrary extra diagnostics
  • Syntax highlighting
  • Stack traces
  • DEBUG_ASSERT_VAL and ASSERT_VAL variants that return a value so they can be integrated seamlessly into code, e.g. FILE* f = ASSERT_VAL(fopen(path, "r") != nullptr)
  • Smart literal formatting
  • Stringification of user-defined types
  • Custom failure handlers
  • Catch2/Gtest integrations
  • {fmt} support
  • Programatic breakpoints on assertion failures for more debugger-friendly assertions, more info below

CMake FetchContent Usage

include(FetchContent)
FetchContent_Declare(
  libassert
  GIT_REPOSITORY https://github.com/jeremy-rifkin/libassert.git
  GIT_TAG        v2.2.1 # 
)
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
    $
    $
  )
endif()

Be sure to configure with -DCMAKE_BUILD_TYPE=Debug or -DDCMAKE_BUILD_TYPE=RelWithDebInfo for symbols and line information.

On macOS it is recommended to generate a .dSYM file, see Platform Logistics below.

For other ways to use the library, such as through package managers or a system-wide installation, see Usage below.

Philosophy

Fundamentally the role of assertions is to verify assumptions made in software and identify violations close to their sources. Assertion tooling should prioritize providing as much information and context to the developer as possible to allow for speedy triage. Unfortunately, existing language and library tooling provides very limited triage information.

For example with stdlib assertions an assertion such as assert(n 10); is automatically understood, as showcased above.

Expression Diagnostics

Values involved in assert expressions are displayed. Redundant diagnostics like 2 => 2 are avoided.

DEBUG_ASSERT(map.count(1) == 2);

Only the full assert expression is able to be extracted from a macro call. Showing which parts of the expression correspond to what values requires some basic expression parsing. C++ grammar is ambiguous but most expressions can be disambiguated.

Extra Diagnostics

All assertions in this library support optional diagnostic messages as well as arbitrary other diagnostic messages.

FILE* f = ASSERT_VAL(fopen(path, "r") != nullptr, "Internal error with foobars", errno, path);

Special handling is provided for errno, and strerror is automatically called.

Note: Extra diagnostics are only evaluated in the failure path of an assertion.

Stack Traces

A lot of work has been put into generating pretty stack traces and formatting them as nicely as possible. Cpptrace is used as a portable and self-contained solution for stacktraces pre-C++23. Optional configurations can be found in the library's documentation.

One feature worth noting is that instead of always printing full paths, only the minimum number of directories needed to differentiate paths are printed.

Another feature worth pointing out is that the stack traces will fold traces with deep recursion:

Syntax Highlighting

The assertion handler applies syntax highlighting wherever appropriate, as seen in all the screenshots above. This is to help enhance readability.

Diff Highlighting

Libassert can provide diff highlighting on output:

This is opt-in with libassert::set_diff_highlighting(true);

Custom Failure Handlers

Libassert supports custom assertion failure handlers:

void handler(const assertion_info& info) {
    throw std::runtime_error("Assertion failed:\n" + assertion.to_string());
}

int main() {
    libassert::set_failure_handler(handler);
}

More details below.

Debug Stringification

A lot of care is given to producing debug stringifications of values as effectively as possible: Strings, characters, numbers, should all be printed as you'd expect. Additionally containers, tuples, std::optional, smart pointers, etc. are all stringified to show as much information as possible. If a user defined type overloads `operator struct libassert::stringifier { std::string stringify(const MyObject& type) { return ...; } };


## Smart literal formatting 

Assertion values are printed in hex or binary as well as decimal if hex/binary are used on either
side of an assertion expression:

```cpp
ASSERT(get_mask() == 0b00001101);

Safe Comparisons

Because expressions are already being automatically decomposed, you can opt into having signed-unsigned comparisons done automatically done with sign safety with -DLIBASSERT_SAFE_COMPARISONS:

ASSERT(18446744073709551606ULL == -10);

…

cpp
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, ...]);

…

cpp
namespace libassert {
    [[nodiscard]] std::string stacktrace(
        int width = 0,
        const color_scheme& scheme = get_color_scheme(),
        std::size_t skip = 0
    );
    [[nodiscard]] std::string print_stacktrace(
        const cpptrace::stacktrace& trace,
        int width = 0,
        const color_scheme& scheme = get_color_scheme(),
        path_mode = get_path_mode()
    );
    template [[nodiscard]] std::string_view type_name() noexcept;
    template [[nodiscard]] std::string pretty_type_name() noexcept;
    template [[nodiscard]] std::string stringify(const T& value);
    std::string highlight(
        std::string_view expression,
        const color_scheme& scheme = get_color_scheme()
    );
    template
    [[nodiscard]] std::string highlight_stringify(
        const T& value,
        const color_scheme& scheme = get_color_scheme()
    );
}
  • stacktrace: Generates a stack trace, formats to the given width (0 for no width formatting)
  • print_stacktrace: Formats a provided stack trace with libassert's internal trace formatting
  • type_name: Returns the type name of T
  • pretty_type_name: Returns the prettified type name for T
  • stringify: Produces a debug stringification of a value
  • highlight: Syntax-highlights a string using libassert's internal expression highlighter
  • highlight_stringify: Equivalent to libassert::highlight(libassert::stringify(value))

Terminal Utilities

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: Enable ANSI escape sequences for terminals on windows, needed for color output.
  • isatty: Returns true if the file descriptor corresponds to a terminal
  • terminal_width: Returns the width of the terminal represented by fd or 0 on error

Configuration

Color Scheme:

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,
                    highlight_delete, highlight_insert, highlight_replace, 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();
}

By default color_scheme::ansi_rgb is used. To disable colors, use color_scheme::blank.

  • set_color_scheme: Sets the color scheme for the default assertion handler when stderr is a terminal

Diff Highlighting:

Diff highlighting is opt-in with set_diff_highlighting:

namespace libassert {
    void set_diff_highlighting(bool);
}

Separator:

namespace libassert {
    void set_separator(std::string_view separator);
}
  • set_separator: Sets the separator between expression and value in assertion diagnostic ou

Issues· 0 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

C++assertionscppdiagnostics

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言