Skip to content

Integer extensions to the C++ Standard Library

"Go to the ant, thou sluggard; consider her ways, and be wise."

Proverbs 6:6, King James Version

"When in doubt, do as the ints do."

Scott Meyers, Effective C++, 3rd edition, Item 18

Project Status: Active License Language Standard OpenSSF Scorecard

xstd-ints is a small, portable, header-only collection of integer extensions to the C++ standard library: concepts, traits, limits, division, alignment and character conversion, open to integer-class types where the standard is closed over the built-ins. It relies on the C++23 standard and targets the draft C++29 standard library. All public APIs are in namespace xstd.

Do as the ints do

Abseil's absl::int128 and Boost.Int128's boost::int128::int128, and their unsigned halves, do as the ints do: they spell out every operator a built-in integer has, specialize std::numeric_limits as integers, and compare with a strong ordering. The standard library does not return the favour. std::integral rests on std::is_integral, which a program may not specialize, so no class type can satisfy it, and the standard's functions over integers, such as those of <bit> and <charconv>, take only the built-in ones. The standard does know class types that behave as integers, the integer-class types of [iterator.concept.winc], but admits only those an implementation supplies itself.

xstd's integer_class asks a type that subclause's questions rather than for its name, so a type that does as the ints do qualifies, and so do the built-in integers it imitates. Abseil's and Boost's 128-bit types qualify as they are. integer asks one thing more, a signed and unsigned pair, named through xstd's specializable make_signed and make_unsigned. Those two sign transformations are all that <xstd/ints/ext/absl/int128.hpp> and <xstd/ints/ext/boost/int128.hpp> adapt.

Headers

The headers come at three levels:

  • <xstd/ints.hpp> includes the whole library, the adaptors aside.
  • An umbrella per standard header the library has counterparts for, named after it: <xstd/ints/bit.hpp> for <bit>, <xstd/ints/cstdlib.hpp> for <cstdlib>, and so on.
  • Beneath each umbrella, in the folder of its name, a header per entity or per family of tightly related entities, such as <xstd/ints/cstdlib/div.hpp> or <xstd/ints/cstdint/int128.hpp> for the 128-bit pair.

The adaptors for third-party libraries sit apart, under <xstd/ints/ext/>. The umbrellas are:

Header Description
<xstd/ints/bit.hpp> The <bit> functions, widened to every unsigned integer with the 128-bit integer classes and _BitInt included, with C++29's bit permutations and shifts by any count.
<xstd/ints/charconv.hpp> std::to_chars, widened to the integers it does not cover, and the buffer size that holds any value at any base.
<xstd/ints/concepts.hpp> Open counterparts of std::integral and its signed and unsigned halves that admit integer-class types, with the bitmask, alignment and noexcept-operator concepts.
<xstd/ints/cstdint.hpp> bit_int<N>, bit_uint<N>, int128 and uint128: the platform's bit-precise and 128-bit integers, where it has them.
<xstd/ints/cstdlib.hpp> abs, unsigned_abs, sign, and truncating, floored, ceiling and Euclidean division of any integer.
<xstd/ints/format.hpp> A std::formatter that writes a division's quotient and remainder.
<xstd/ints/limits.hpp> An open std::numeric_limits, specialized for the bit-precise integers.
<xstd/ints/memory.hpp> Rounding a value up or down to a power-of-two alignment, and testing whether it is aligned.
<xstd/ints/type_traits.hpp> Open sign traits and sign transformations, which users may specialize, and the type an integer's own operators yield.
<xstd/ints/ext/absl.hpp> Pairs Abseil's int128 and uint128, so that each models integer.
<xstd/ints/ext/boost.hpp> Pairs Boost.Int128's 128-bit integers, and hashes any integer's value into a Boost.Hash2 algorithm.

The reference lists each group's headers and specifies each entity, the design notes give the rationale and how to customize an integer-class type, and the measurements the evidence. CONTRIBUTING.md builds the library itself.

Usage

#include <xstd/ints/cstdlib.hpp>
#include <xstd/ints/memory.hpp>
#include <climits>

static_assert(xstd::unsigned_abs(INT_MIN) == static_cast<unsigned>(INT_MAX) + 1u);
static_assert(xstd::align_up(100uz, 64) == 128);
static_assert(xstd::align_down(100uz, 64) == 64);
static_assert(not xstd::is_aligned(100uz, 64));

constexpr auto result = xstd::div_euclid(-8, 3);
static_assert(result.quotient == -3);
static_assert(result.remainder == 1);

If you lint with clang-tidy and use any Boost library, misc-include-cleaner reports that nothing provides the Boost names you write: no Boost library ships the IWYU pragmas the check reads. The answer is one line in your own .clang-tidy, which no library can supply for you:

CheckOptions:
  misc-include-cleaner.IgnoreHeaders: 'boost/.*'

Requirements

  • A conforming C++23 compiler
  • CMake 3.30 or later when using the supplied CMake project
  • No third-party runtime or library dependencies outside <xstd/ints/ext/>

<xstd/ints/format.hpp> is the only header that depends on <format>. The front door <xstd/ints.hpp> exports it along with everything else, so a translation unit that wants no <format> names the domain umbrellas it uses instead: none of those reaches it. The <xstd/ints/ext/> headers are the only ones that include a third-party library, and no other header includes them: an adapted library is reached by naming it.

Installation

The usual approach is CMake's FetchContent:

include(FetchContent)
FetchContent_Declare(
    xstd-ints
    GIT_REPOSITORY https://github.com/rhalbersma/xstd-ints.git
    GIT_TAG main # Prefer a release tag for reproducible builds.
)
FetchContent_MakeAvailable(xstd-ints)

target_link_libraries(my_target PRIVATE xstd::ints)

find_package(xstd-ints CONFIG REQUIRED) and add_subdirectory(external/xstd-ints) provide the same xstd::ints target.

Continuous Integration

We continuously test the stable, qualification, and development branches of the major C++23 toolchains (compilers and standard libraries) in both Debug and Release mode:

Platform Compiler Standard Library Stable Qualification Development Status
Linux GCC libstdc++ 15 16 17-SVN GCC
Windows MinGW libstdc++ 15 16 — MinGW
Linux Clang libstdc++ 22 (libstdc++ 15) 23 (libstdc++ 16) 24-SVN (libstdc++ 17-SVN) Clang
Linux Clang libc++ 22 23 24-SVN Clang-libc++
macOS Apple Clang libc++ 17.0.0 (Xcode 16.4) 21.0.0 (Xcode 26.6) — Apple Clang
Windows Clang-CL MSVC 19.1.5 (VS 2022) 20.1.8 (VS 2026) 20.1.8 (VS 2026-Preview) Clang-CL
Windows MSVC MSVC 2022 (17.11+) 2026 2026-Preview MSVC
Web Emscripten libc++ 6.0.12 — — Emscripten
s390x GCC libstdc++ 15 — — s390x

CONTRIBUTING.md says what each channel is, and which legs run beyond the table.

Beyond the compilers, CI holds coverage at 100%, tests the tests by mutation, consumes the library through find_package, add_subdirectory and FetchContent, runs the sanitizers, analyzes the code with Clang-Tidy, MSVC's /analyze and CodeQL, and builds the documentation site:

Coverage Mutation Consumption Sanitizers Clang-Tidy MSVC-Analyze CodeQL Documentation

License

         Copyright Rein Halbersma 2014-2026.
Distributed under the Boost Software License, Version 1.0.
   (See accompanying file LICENSE_1_0.txt or copy at
         http://www.boost.org/LICENSE_1_0.txt)