SkillAgentSearch skills...

Libassert

The most over-engineered C++ assertion library

Install / Use

/learn @jeremy-rifkin/Libassert
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

libassert <!-- omit in toc -->

ci Quality Gate Status <br/> Community Discord Link

<!-- <br/> [![Try on Compiler Explorer](https://img.shields.io/badge/-Compiler%20Explorer-brightgreen?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAQCAYAAAAmlE46AAAACXBIWXMAAACwAAAAsAEUaqtpAAABSElEQVQokYVTsU7DMBB9QMTCEJbOMLB5oF0tRfUPIPIJZctYJkZYu3WMxNL+ARUfQKpImcPgDYnsXWBgYQl61TkYyxI3Wef37j3fnQ/6vkcsikY9AbiWq0mpbevDBmLRqDEAA4CEHMADgFRwrwDmch6X2i73RCFVHvC/WCeCMAFpC2AFoPPu5x4md4rnAN4luS61nYWSgauNU8ydkr0bLTMYAoIYtWqxM4LtEumeERDtfUjlMDrp7L67iddyyJtOvUIu2rquVn4iiVSOKXYhiMSJWLwUJZLuQ2CWmVldV4MT11UmXgB8fr0dX3WP6VHMiVrscim6Da2mJxffzwSU2v6xWzSKmzQ4cUTOaCBTvWgU14xkzjhckKm/q3wnrRAcAhksxMZNAdxEf0fRKI6E8zqT1C0X28ccRpqAUltW5pu4sxv5Mb8B4AciE3bHMxz/+gAAAABJRU5ErkJggg==&labelColor=2C3239&style=flat&label=Try+it+on&color=30C452)](https://godbolt.org/z/Eonafvxof) --> <p align="center">The most over-engineered C++ assertion library</p>

Table of Contents: <!-- omit in toc -->

30-Second Overview

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

Some of the awesome things the library does:

#include <libassert/assert.hpp>
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());

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 # <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()

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 <= 12); provides no information upon failure about why it failed or what led to its failure. Providing a stack trace and the value of n greatly improves triage and debugging. Ideally an assertion failure should provide enough diagnostic information that the programmmer doesn't have to rerun in a debugger to pinpoint the problem.

Version 1 of this library was an exploration looking at how much helpful information and functionality could be packed into assertions while also providing a quick and easy interface for the developer.

Version 2 of this library takes lessons learned from version 1 to create a tool that I personally have found indispensable in development.

Features

Automatic Expression Decomposition <!-- omit in toc -->

The most important feature this library supports is automatic expression decomposition. No need for ASSERT_LT or other such hassle, assert(vec.size() > 10); is automatically understood, as showcased above.

Expression Diagnostics <!-- omit in toc -->

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 <!-- omit in toc -->

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 <!-- omit in toc -->

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 <!-- omit in toc -->

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

Diff Highlighting <!-- omit in toc -->

Libassert can provide diff highlighting on output:

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

Custom Failure Handlers <!-- omit in toc -->

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 <!-- omit in toc -->

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 us

Related Skills

View on GitHub
GitHub Stars712
CategoryDevelopment
Updated3d ago
Forks52

Languages

C++

Security Score

100/100

Audited on Apr 2, 2026

No findings