Miscellaneous extensions to the C++ Standard Library¶
‘The time has come,’ the Walrus said,
‘To talk of many things:
Of shoes—and ships—and sealing-wax—
Of cabbages—and kings—
And why the sea is boiling hot—
And whether pigs have wings.’— Lewis Carroll, Through the Looking-Glass (1871), "The Walrus and the Carpenter"
xstd-misc is a header-only collection of small extensions to the C++ standard library: what the xstd family needs
beyond integers, which xstd-ints holds, and bit containers, which
xstd-bits holds. Each facility lives under the standard header it extends.
Boost.Hash2 is the one dependency. The library relies on the
C++20 standard and targets the draft C++29 standard library, and
every public API is in namespace xstd.
Headers¶
The headers come at three levels:
<xstd/misc.hpp>includes the whole library.- An umbrella per standard header the library has counterparts for, named after it:
<xstd/misc/utility.hpp>for<utility>,<xstd/misc/functional.hpp>for<functional>, and so on. - Beneath each umbrella, in the folder of its name, a header per entity, such as
<xstd/misc/utility/to_underlying.hpp>.
The umbrellas are:
| Header | Description |
|---|---|
<xstd/misc/concepts.hpp> |
The proxy concepts, a Boost.Hash2 hash algorithm, specialization_of, and two exposition-only concepts copied from the standard. |
<xstd/misc/format.hpp> |
A std::formatter that writes a Boost.Hash2 digest as hex. |
<xstd/misc/functional.hpp> |
hash and digest: an unordered container's hash and a key's digest, from a seeded Boost.Hash2 algorithm. |
<xstd/misc/type_traits.hpp> |
is_specialization_of, whether a hash algorithm avalanches, XSTD_NO_UNIQUE_ADDRESS, and the types that keep the place of a base or member that may be absent. |
<xstd/misc/utility.hpp> |
std::to_underlying, extended to an enumerator in std::integral_constant and to a proxy reference to one. |
The reference lists each group's headers and specifies each entity, the design notes give the rationale, and the measurements the evidence behind it. CONTRIBUTING.md builds the library itself.
Usage¶
An unordered container whose keys an adversary may choose takes SipHash, seeded per container, as
Hash2 advises.
SipHash's key is 128 bits, which a 16-byte seed fills and a std::uint64_t seed only half fills:
#include <xstd/misc/functional.hpp>
#include <boost/hash2/siphash.hpp>
#include <array>
#include <string>
#include <unordered_set>
using siphasher = xstd::hash<std::string, boost::hash2::siphash_64>;
auto const key = std::array<unsigned char, 16>{/* drawn at random, per container */};
auto names = std::unordered_set<std::string, siphasher>(0, siphasher(key.data(), key.size()));
If you lint with clang-tidy, misc-include-cleaner reports that nothing provides the Boost names you write, here and
anywhere else you use Boost: 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++20 compiler
- CMake 3.30 or later when using the supplied CMake project
- Boost.Hash2 1.89 or later, the first with
xxh3_128, header-only, which thexstd::misctarget links and its installed package finds
CI covers the toolchains in the table below, and no older ones.
Installation¶
The usual approach is CMake's FetchContent:
include(FetchContent)
FetchContent_Declare(
xstd-misc
GIT_REPOSITORY https://github.com/rhalbersma/xstd-misc.git
GIT_TAG main # Prefer a release tag for reproducible builds.
)
FetchContent_MakeAvailable(xstd-misc)
target_link_libraries(my_target PRIVATE xstd::misc)
find_package(xstd-misc CONFIG REQUIRED) and add_subdirectory(external/xstd-misc) provide
the same xstd::misc target. Each finds Boost.Hash2 with find_package(boost_hash2 CONFIG), so it
must be installed where CMake looks, as vcpkg's boost-hash2 port or Boost 1.89+ puts it.
To build and install the headers alone, without the test suite and its Boost.Test dependency, configure with tests off:
cmake --preset no-tests # or: cmake -S . -B build -DBUILD_TESTING=OFF
cmake --install build/no-tests --prefix /usr/local
Tests are built only when xstd-misc is the top-level project, so a FetchContent or
add_subdirectory consumer never needs Boost.Test.
Continuous Integration¶
We continuously test the stable, qualification, and development branches of the major C++20 toolchains (compilers and standard libraries) in both Debug and Release mode:
CONTRIBUTING.md says what each channel is, and which legs run beyond the table.
Beyond the compilers, CI holds coverage at 100%, consumes the library through find_package, add_subdirectory and
FetchContent, runs the sanitizers, analyzes the code with Clang-Tidy, MSVC's /analyze and CodeQL, deletes each
clause of each constraint to check that a test notices, and builds the documentation site:
Acknowledgements¶
We acknowledge Walter E. Brown for discussing the idea for std::to_underlying
and JeanHeyd Meneide for drafting it into an actual proposal and shepherding
P1682 through the C++ standardization process.
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)
The examples under examples/cppreference/, ported from cppreference.com, are the
exception: as that site's content is, they are under the Creative Commons Attribution-ShareAlike 3.0 Unported License
and the GNU Free Documentation License, which their licence file gives in full.