Core module

Small, generally-useful functions and types.

Modules

module Metafunctions and type traits
Type traits and metaprogramming utilities.

Classes

template <typename First, typename Second>
class muu::compressed_pair
A pair that uses Empty Base Class Optimization to elide storage for one or both of its members where possible.
struct muu::half
A 16-bit "half-precision" IEEE754 floating point type.
template <typename T>
struct muu::integral_range
A half-open range of integral values (ints, enums, pointers).
template <typename T>
class muu::scope_fail
Performs actions when going out of scope due to an exception being thrown.
template <typename T>
class muu::scope_guard
Performs actions when going out of scope.
template <typename T>
class muu::scope_success
Performs actions when going out of scope only if no exceptions have been thrown.
template <typename T, size_t Extent = dynamic_extent, size_t Alignment = 0>
class muu::span
A non-owning view of contiguous elements.
template <typename ValueType, typename Tag, template<typename> typename... Traits>
struct muu::strong_typedef
A utility class for creating 'strong typedefs'.
template <typename T, size_t Align = impl::tptr_min_align<T>>
class muu::tagged_ptr
Specialized pointer capable of storing data in the unused bits of a pointer's value.
struct muu::uuid
A 128-bit universally-unique identifier (UUID).

Typedefs

using byteptr_range = integral_range<std::byte*>
Convenience alias for integral_range<std::byte*>.
using float128_t = __float128
A 128-bit quad-precision float.
using index_range = integral_range<size_t>
Convenience alias for integral_range<size_t>.
using int128_t = __int128_t
A 128-bit signed integer.
using intptr_range = integral_range<intptr_t>
Convenience alias for integral_range<intptr_t>.
using uint128_t = __uint128_t
A 128-bit unsigned integer.
using uintptr_range = integral_range<uintptr_t>
Convenience alias for integral_range<uintptr_t>.

Functions

auto aligned_alloc(size_t size, size_t alignment) -> void* noexcept
Allocates memory on a specific alignment boundary.
void aligned_free(void* ptr) noexcept
Frees memory that was allocated using muu::aligned_alloc().
template <size_t Alignment, typename T>
auto apply_alignment(T val) -> T constexpr noexcept
Rounds an unsigned value up to the next multiple of the given alignment.
template <size_t Alignment, typename T>
auto apply_alignment(T* ptr) -> T* constexpr noexcept
Rounds a pointer up to the byte offset that is the next multiple of the given alignment.
template <typename T>
auto apply_alignment(T val, size_t alignment) -> T constexpr noexcept
Rounds an unsigned value up to the next multiple of the given alignment.
template <typename T>
auto apply_alignment(T* ptr, size_t alignment) -> T* constexpr noexcept
Rounds a pointer up to the byte offset that is the next multiple of the given alignment.
template <typename T, typename Offset>
auto apply_offset(T* ptr, Offset offset) -> T* constexpr noexcept
Applies a byte offset to a pointer.
template <size_t N, typename T>
auto assume_aligned(T* ptr) -> T* constexpr noexcept
Equivalent to C++20's std::assume_aligned.
template <typename T, typename U>
auto between(const T& val, const U& low, const U& high) -> bool constexpr noexcept
Returns true if a value is between two bounds (inclusive).
template <typename To, typename From>
auto bit_cast(const From& from) -> To constexpr noexcept
Equivalent to C++20's std::bit_cast.
template <typename T>
auto bit_ceil(T val) -> T constexpr noexcept
Finds the smallest integral power of two not less than the given value.
template <typename T>
auto bit_fill_left(size_t count) -> T constexpr noexcept
Returns an unsigned integer filled from the left with the desired number of consecutive ones.
template <typename T>
auto bit_fill_right(size_t count) -> T constexpr noexcept
Returns an unsigned integer filled from the right with the desired number of consecutive ones.
template <typename T>
auto bit_floor(T val) -> T constexpr noexcept
Finds the largest integral power of two not greater than the given value.
template <typename Return = void, typename T, typename U, typename... V>
auto bit_pack(T val1, U val2, V... vals) -> auto constexpr noexcept
Bitwise-packs integers left-to-right into a larger integer.
template <typename T>
auto bit_width(T val) -> T constexpr noexcept
Finds the smallest number of bits needed to represent the given value.
template <typename T>
auto byte_reverse(T val) -> T constexpr noexcept
Reverses the byte order of an unsigned integral type.
template <size_t Index, typename T>
auto byte_select(T val) -> uint8_t constexpr noexcept
Gets a specific byte from an integer.
template <typename T>
auto byte_select(T val, size_t index) -> uint8_t constexpr noexcept
Gets a specific byte from an integer.
template <typename T>
auto clamp(const T& val, const T& low, const T& high) -> const T& constexpr noexcept
Returns a value clamped between two bounds (inclusive).
template <typename T>
auto countl_one(T val) -> int constexpr noexcept
Counts the number of consecutive 1 bits, starting from the left.
template <typename T>
auto countl_zero(T val) -> int constexpr noexcept
Counts the number of consecutive 0 bits, starting from the left.
template <typename T>
auto countr_one(T val) -> int constexpr noexcept
Counts the number of consecutive 1 bits, starting from the right.
template <typename T>
auto countr_zero(T val) -> int constexpr noexcept
Counts the number of consecutive 0 bits, starting from the right.
template <auto N1, auto N2, typename Func>
void for_product(Func&& func) constexpr noexcept(…)
Generates a series of sequential function calls by pack expansion.
template <auto N, typename Func>
void for_sequence(Func&& func) constexpr noexcept(…)
Generates a series of sequential function calls by pack expansion.
template <typename T>
auto has_single_bit(T val) -> bool constexpr noexcept
Checks if an integral value has only a single bit set.
auto is_constant_evaluated() -> bool constexpr noexcept
Equivalent to C++20's std::is_constant_evaluated.
template <class T>
auto launder(T* ptr) -> T* constexpr noexcept
Equivalent to C++17's std::launder.
template <typename T, typename... U>
auto max(const T& val1, const T& val2, const U&... vals) -> const T& constexpr noexcept
Returns the maximum of two or more values.
template <typename T, typename... U>
auto min(const T& val1, const T& val2, const U&... vals) -> const T& constexpr noexcept
Returns the minimum of two or more values.
template <typename To, typename From>
auto pointer_cast(From from) -> To constexpr noexcept
Casts between pointers, choosing the most appropriate conversion path.
template <typename T>
auto popcount(T val) -> int constexpr noexcept
Counts the number of set bits (the 'population count') of an unsigned integer.
template <typename F, typename S>
void swap(compressed_pair<F, S>& lhs, compressed_pair<F, S>& rhs) noexcept(…)
Swaps two compressed pairs.
template <size_t... ByteIndices, typename T>
auto swizzle(T val) -> auto constexpr noexcept
Select and re-pack arbitrary bytes from an integer.
template <typename T>
auto to_address(T* p) -> T* constexpr noexcept
Obtain the address represented by p without forming a reference to the pointee.
template <typename Ptr>
auto to_address(const Ptr& p) -> auto constexpr noexcept
Obtain the address represented by p without forming a reference to the pointee.
template <typename T>
auto unwrap(T val) -> std::underlying_type_t<T> constexpr noexcept
Unwraps an enum to it's raw integer equivalent.

Typedef documentation

using byteptr_range = integral_range<std::byte*>

Convenience alias for integral_range<std::byte*>.

using float128_t = __float128
#include <muu/fwd.h>

A 128-bit quad-precision float.

using index_range = integral_range<size_t>

Convenience alias for integral_range<size_t>.

using int128_t = __int128_t
#include <muu/fwd.h>

A 128-bit signed integer.

using intptr_range = integral_range<intptr_t>

Convenience alias for integral_range<intptr_t>.

using uint128_t = __uint128_t
#include <muu/fwd.h>

A 128-bit unsigned integer.

using uintptr_range = integral_range<uintptr_t>

Convenience alias for integral_range<uintptr_t>.

Function documentation

void* aligned_alloc(size_t size, size_t alignment) noexcept

Allocates memory on a specific alignment boundary.

void aligned_free(void* ptr) noexcept

Frees memory that was allocated using muu::aligned_alloc().

template <size_t Alignment, typename T>
T apply_alignment(T val) constexpr noexcept

Rounds an unsigned value up to the next multiple of the given alignment.

Template parameters
Alignment The alignment to round up to. Must be a power of two.
T An unsigned integer or enum type.
Parameters
val The unsigned value being aligned.

template <size_t Alignment, typename T>
T* apply_alignment(T* ptr) constexpr noexcept

Rounds a pointer up to the byte offset that is the next multiple of the given alignment.

Template parameters
Alignment The alignment to round up to. Must be a power of two.
T An object type (or void).
Parameters
ptr The pointer being aligned.

template <typename T>
T apply_alignment(T val, size_t alignment) constexpr noexcept

Rounds an unsigned value up to the next multiple of the given alignment.

Template parameters
T An unsigned integer or enum type.
Parameters
val The unsigned value being aligned.
alignment The alignment to round up to. Must be a power of two.

template <typename T>
T* apply_alignment(T* ptr, size_t alignment) constexpr noexcept

Rounds a pointer up to the byte offset that is the next multiple of the given alignment.

Template parameters
T An object type (or void).
Parameters
ptr The pointer being aligned.
alignment The alignment to round up to. Must be a power of two.

#include <muu/core.h>
template <typename T, typename Offset>
T* apply_offset(T* ptr, Offset offset) constexpr noexcept

Applies a byte offset to a pointer.

Template parameters
T The type being pointed to.
Offset An integer type.
Parameters
ptr The pointer to offset.
offset The number of bytes to add to the pointer's address.
Returns The cv-correct equivalent of (T*)((std::byte*)ptr + offset).

template <size_t N, typename T>
T* assume_aligned(T* ptr) constexpr noexcept

Equivalent to C++20's std::assume_aligned.

#include <muu/core.h>
template <typename T, typename U>
bool between(const T& val, const U& low, const U& high) constexpr noexcept

Returns true if a value is between two bounds (inclusive).

template <typename To, typename From>
To bit_cast(const From& from) constexpr noexcept

Equivalent to C++20's std::bit_cast.

template <typename T>
T bit_ceil(T val) constexpr noexcept

Finds the smallest integral power of two not less than the given value.

Template parameters
T An unsigned integer or enum type.
Parameters
val The input value.
Returns The smallest integral power of two that is not smaller than val.

template <typename T>
T bit_fill_left(size_t count) constexpr noexcept

Returns an unsigned integer filled from the left with the desired number of consecutive ones.

Template parameters
T An unsigned integer type.
Parameters
count Number of consecutive ones.
Returns An instance of T left-filled with the desired number of ones.
const auto val1 = bit_fill_left<uint32_t>(5);
const auto val2 = 0b11111000000000000000000000000000u;
assert(val1 == val2);

template <typename T>
T bit_fill_right(size_t count) constexpr noexcept

Returns an unsigned integer filled from the right with the desired number of consecutive ones.

Template parameters
T An unsigned integer type.
Parameters
count Number of consecutive ones.
Returns An instance of T right-filled with the desired number of ones.
const auto val1 = bit_fill_right<uint32_t>(5);
const auto val2 = 0b00000000000000000000000000011111u;
assert(val1 == val2);

template <typename T>
T bit_floor(T val) constexpr noexcept

Finds the largest integral power of two not greater than the given value.

Template parameters
T An unsigned integer or enum type.
Parameters
val The input value.
Returns Zero if val is zero; otherwise, the largest integral power of two that is not greater than val.

template <typename Return = void, typename T, typename U, typename... V>
auto bit_pack(T val1, U val2, V... vals) constexpr noexcept

Bitwise-packs integers left-to-right into a larger integer.

Template parameters
Return An integer or enum type, or leave as void to choose an unsigned type based on the total size of the inputs.
T An integer or enum type.
U An integer or enum type.
V Integer or enum types.
Parameters
val1 The left-most value to be packed.
val2 The second-left-most value to be packed.
vals Any remaining values to be packed.
Returns An integral value containing the input values packed bitwise left-to-right. If the total size of the inputs was less than the return type, the output will be zero-padded on the left.
auto   val1  = bit_pack(0xAABB_u16, 0xCCDD_u16);
assert(val1 == 0xAABBCCDD_u32);

auto   val2  = bit_pack(0xAABB_u16, 0xCCDD_u16, 0xEEFF_u16);
assert(val2 == 0x0000AABBCCDDEEFF_u64);
              // ^^^^ input was 48 bits, zero-padded to 64 on the left

#include <muu/bit.h>
template <typename T>
T bit_width(T val) constexpr noexcept

Finds the smallest number of bits needed to represent the given value.

Template parameters
T An unsigned integer or enum type.
Parameters
val The input value.
Returns If val is not zero, calculates the number of bits needed to store val (i.e. 1 + log2(x)). Returns 0 if val is zero.

template <typename T>
T byte_reverse(T val) constexpr noexcept

Reverses the byte order of an unsigned integral type.

Template parameters
T An unsigned integer or enum type.
Parameters
val An unsigned integer or enum value.
Returns A copy of the input value with the byte order reversed.
const auto i = 0xAABBCCDDu;
const auto j = byte_reverse(i);
std::cout << std::hex << i << "\n" << j;
AABBCCDD
DDCCBBAA

#include <muu/bit.h>
template <size_t Index, typename T>
uint8_t byte_select(T val) constexpr noexcept

Gets a specific byte from an integer.

Template parameters
Index Index of the byte to retrieve.
T An integer or enum type.
Parameters
val An integer or enum value.
Returns The value of the selected byte.
const auto i = 0xAABBCCDDu;
//                ^ ^ ^ ^
// byte indices:  3 2 1 0

std::cout << std::hex;
std::cout << "0: " << byte_select<0>(i) << "\n";
std::cout << "1: " << byte_select<1>(i) << "\n";
std::cout << "2: " << byte_select<2>(i) << "\n";
std::cout << "3: " << byte_select<3>(i) << "\n";
0: DD
1: CC
2: BB
3: AA
(on a little-endian system)

#include <muu/bit.h>
template <typename T>
uint8_t byte_select(T val, size_t index) constexpr noexcept

Gets a specific byte from an integer.

Template parameters
T An integer or enum type.
Parameters
val An integer or enum value.
index Index of the byte to retrieve.
Returns The value of the selected byte, or 0 if the index was out-of-range.
const auto i = 0xAABBCCDDu;
//                ^ ^ ^ ^
// byte indices:  3 2 1 0

std::cout << std::hex;
std::cout << "0: " << byte_select(i, 0) << "\n";
std::cout << "1: " << byte_select(i, 1) << "\n";
std::cout << "2: " << byte_select(i, 2) << "\n";
std::cout << "3: " << byte_select(i, 3) << "\n";
0: DD
1: CC
2: BB
3: AA
(on a little-endian system)

#include <muu/core.h>
template <typename T>
const T& clamp(const T& val, const T& low, const T& high) constexpr noexcept

Returns a value clamped between two bounds (inclusive).

template <typename T>
int countl_one(T val) constexpr noexcept

Counts the number of consecutive 1 bits, starting from the left.

Template parameters
T An unsigned integer or enum type.
Parameters
val The value to test.
Returns The number of consecutive ones from the left end of an integer's bits.

template <typename T>
int countl_zero(T val) constexpr noexcept

Counts the number of consecutive 0 bits, starting from the left.

Template parameters
T An unsigned integer or enum type.
Parameters
val The value to test.
Returns The number of consecutive zeros from the left end of an integer's bits.

template <typename T>
int countr_one(T val) constexpr noexcept

Counts the number of consecutive 1 bits, starting from the right.

Template parameters
T An unsigned integer or enum type.
Parameters
val The value to test.
Returns The number of consecutive ones from the right end of an integer's bits.

template <typename T>
int countr_zero(T val) constexpr noexcept

Counts the number of consecutive 0 bits, starting from the right.

Template parameters
T An unsigned integer or enum type.
Parameters
val The input value.
Returns The number of consecutive zeros from the right end of an integer's bits.

template <auto N1, auto N2, typename Func>
void for_product(Func&& func) constexpr noexcept(…)

Generates a series of sequential function calls by pack expansion.

Template parameters
N1 The length of the LHS sequence. Cannot be negative.
N2 The length of the RHS sequence. Cannot be negative.
Func A callable type with the signature void(auto, auto).

Generates a std::integral_constant cartesian product sequence, [0...N1) * [0...N2), which is passed into the callable:

auto vals_1 = std::pair{ 1, 2 };
auto vals_2 = std::pair{ 3, 4 };
for_product<2, 2>([&](auto i, auto j)
{
    const auto lhs = std::get<decltype(i)::value>(vals_1);
    const auto rhs = std::get<decltype(j)::value>(vals_2);
    std::cout << lhs
              << " * "
              << rhs
              << " = "
              << lhs * rhs;
});
1 * 3 = 3
1 * 4 = 4
2 * 3 = 6
2 * 4 = 8

template <auto N, typename Func>
void for_sequence(Func&& func) constexpr noexcept(…)

Generates a series of sequential function calls by pack expansion.

Template parameters
N The length of the sequence (the number of calls). Cannot be negative.
Func A callable type with the signature void(auto).

Generates a std::integral_constant sequence, [0...N1), which is passed into the callable:

auto vals = std::tuple{ 0, "1"sv, 2.3f };
for_sequence<3>([&](auto i)
{
    std::cout << std::get<decltype(i)::value>(vals) << "\n";
});
0
1
2.3

template <typename T>
bool has_single_bit(T val) constexpr noexcept

Checks if an integral value has only a single bit set.

Template parameters
T An unsigned integer or enum type.
Parameters
val The value to test.
Returns True if the input value had only a single bit set (and thus was a power of two).

bool is_constant_evaluated() constexpr noexcept

Equivalent to C++20's std::is_constant_evaluated.

template <class T>
T* launder(T* ptr) constexpr noexcept

Equivalent to C++17's std::launder.

#include <muu/core.h>
template <typename T, typename... U>
const T& max(const T& val1, const T& val2, const U&... vals) constexpr noexcept

Returns the maximum of two or more values.

#include <muu/core.h>
template <typename T, typename... U>
const T& min(const T& val1, const T& val2, const U&... vals) constexpr noexcept

Returns the minimum of two or more values.

template <typename To, typename From>
To pointer_cast(From from) constexpr noexcept

Casts between pointers, choosing the most appropriate conversion path.

Template parameters
To A pointer or integral type large enough to store a pointer
From A pointer, array, nullptr_t, or an integral type large enough to store a pointer.
Parameters
from The value being cast.
Returns The input casted to the desired type.

Doing low-level work with pointers often requires a lot of tedious boilerplate, particularly when moving to/from raw byte representations or dealing with const. By using pointer_cast instead you can eliminate a lot of that boilerplate, since it will do 'the right thing' via some combination of:

FromToCastNote
T*void*static_cast
void*T*static_cast
T*const T*static_cast
T*volatile T*static_cast
T*const volatile T*static_cast
const T*T*const_cast
volatile T*T*const_cast
const volatile T*T*const_cast
Derived*Base*static_cast
Base*Derived*dynamic_castPolymorphic bases
Base*Derived*static_castNon-polymorphic bases
T*(u)intptr_treinterpret_cast
(u)intptr_tT*reinterpret_cast
void*T(*)()reinterpret_castWhere supported
T(*)()void*reinterpret_castWhere supported
T(*)()T(*)()noexceptreinterpret_cast
T(*)()noexceptT(*)()static_cast
IUnknown*IUnknown*QueryInterfaceWindows only

template <typename T>
int popcount(T val) constexpr noexcept

Counts the number of set bits (the 'population count') of an unsigned integer.

Template parameters
T An unsigned integer or enum type.
Parameters
val The input value.
Returns The number of bits that were set to 1 in val.

template <typename F, typename S>
void swap(compressed_pair<F, S>& lhs, compressed_pair<F, S>& rhs) noexcept(…)

Swaps two compressed pairs.

#include <muu/bit.h>
template <size_t... ByteIndices, typename T>
auto swizzle(T val) constexpr noexcept

Select and re-pack arbitrary bytes from an integer.

Template parameters
ByteIndices Indices of the bytes from the source integer in the (little-endian) order they're to be packed.
T An integer or enum type.
Parameters
val An integer or enum value.
Returns An integral value containing the selected bytes packed bitwise left-to-right. If the total size of the inputs was less than the return type, the output will be zero-padded on the left.
const auto i = 0xAABBCCDDu;
//                ^ ^ ^ ^
// byte indices:  3 2 1 0

std::cout << std::hex << std::setfill('0');
std::cout << "      <0>: " << std::setw(8) <<       swizzle<0>(i) << "\n";
std::cout << "   <1, 0>: " << std::setw(8) <<    swizzle<1, 0>(i) << "\n";
std::cout << "<3, 2, 3>: " << std::setw(8) << swizzle<3, 2, 3>(i) << "\n";
      <0>: 000000DD
   <1, 0>: 0000CCDD
<3, 2, 3>: 00AABBAA
(on a little-endian system)

#include <muu/core.h>
template <typename T>
T* to_address(T* p) constexpr noexcept

Obtain the address represented by p without forming a reference to the pointee.

#include <muu/core.h>
template <typename Ptr>
auto to_address(const Ptr& p) constexpr noexcept

Obtain the address represented by p without forming a reference to the pointee.

#include <muu/core.h>
template <typename T>
std::underlying_type_t<T> unwrap(T val) constexpr noexcept

Unwraps an enum to it's raw integer equivalent.

Template parameters
T An enum type.
Parameters
val The value to unwrap.
Returns Enum inputs: static_cast<std::underlying_type_t<T>>(val)
Everything else: T&& (a no-op).