Random Number Generation
Description
The library provides a boost::random::uniform_int_distribution specialization for all safe integer types, enabling uniform random number generation that returns safe integers directly.
This works with any standard or Boost random engine (std::mt19937, std::mt19937_64, boost::random::mt19937, etc.).
All unsigned types (u8, u16, u32, u64, u128), signed types (i8, i16, i32, i64, i128), and bounded_uint<Min, Max> are supported.
The header <boost/safe_numbers/random.hpp> is NOT included in the convenience header <boost/safe_numbers.hpp>, because it requires Boost.Random to be present.
You must include it explicitly.
|
#include <boost/safe_numbers.hpp> // Does NOT include random support
#include <boost/safe_numbers/random.hpp> // Must be included separately
Synopsis
#include <boost/safe_numbers/random.hpp>
namespace boost::random {
template <typename SafeT>
requires (safe_numbers::detail::is_unsigned_library_type_v<SafeT> ||
safe_numbers::detail::is_signed_library_type_v<SafeT>)
class uniform_int_distribution<SafeT>
{
public:
class param_type
{
public:
explicit param_type(
SafeT min = std::numeric_limits<SafeT>::min(),
SafeT max = std::numeric_limits<SafeT>::max());
auto a() const -> SafeT;
auto b() const -> SafeT;
friend bool operator==(const param_type& lhs, const param_type& rhs);
friend bool operator!=(const param_type& lhs, const param_type& rhs);
// Stream I/O
template <class CharT, class Traits>
friend std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os, const param_type& p);
template <class CharT, class Traits>
friend std::basic_istream<CharT, Traits>&
operator>>(std::basic_istream<CharT, Traits>& is, param_type& p);
};
explicit uniform_int_distribution(
SafeT min = std::numeric_limits<SafeT>::min(),
SafeT max = std::numeric_limits<SafeT>::max());
explicit uniform_int_distribution(const param_type& param);
// Generation
template <typename Engine>
auto operator()(Engine& eng) const -> SafeT;
template <typename Engine>
auto operator()(Engine& eng, const param_type& param) const -> SafeT;
// Observers
auto min() const -> SafeT;
auto max() const -> SafeT;
auto a() const -> SafeT;
auto b() const -> SafeT;
param_type param() const;
void param(const param_type& p);
void reset();
// Comparison
friend bool operator==(const uniform_int_distribution& lhs,
const uniform_int_distribution& rhs);
friend bool operator!=(const uniform_int_distribution& lhs,
const uniform_int_distribution& rhs);
// Stream I/O
template <class CharT, class Traits>
friend std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os,
const uniform_int_distribution& ud);
template <class CharT, class Traits>
friend std::basic_istream<CharT, Traits>&
operator>>(std::basic_istream<CharT, Traits>& is,
uniform_int_distribution& ud);
};
} // namespace boost::random
Bounded Types
For bounded_uint<Min, Max>, the default range is the declared bounds of the type:
using percent = bounded_uint<u8{0}, u8{100}>;
boost::random::uniform_int_distribution<percent> pct_dist;
auto pct = pct_dist(rng); // percent in [0, 100]
Examples
Example 1. This example demonstrates generating uniformly distributed safe integer values.
// Copyright 2026 Matt Borland
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/safe_numbers.hpp>
#include <boost/safe_numbers/random.hpp>
#include <iostream>
#include <random>
int main()
{
using namespace boost::safe_numbers;
std::mt19937_64 rng{42};
// Generate uniformly distributed unsigned values
boost::random::uniform_int_distribution<u32> u32_dist{u32{1}, u32{100}};
std::cout << "u32 in [1, 100]: " << u32_dist(rng) << std::endl;
// Generate uniformly distributed signed values
boost::random::uniform_int_distribution<i32> i32_dist{i32{-50}, i32{50}};
std::cout << "i32 in [-50, 50]: " << i32_dist(rng) << std::endl;
// Default range uses the full range of the type
boost::random::uniform_int_distribution<u64> u64_dist;
std::cout << "u64 full range: " << u64_dist(rng) << std::endl;
// Use param_type to change range without reconstructing
using dist_t = boost::random::uniform_int_distribution<u16>;
dist_t dist;
dist_t::param_type narrow{u16{0}, u16{10}};
std::cout << "u16 in [0, 10]: " << dist(rng, narrow) << std::endl;
// 128-bit types work too
boost::random::uniform_int_distribution<u128> u128_dist{u128{0U}, u128{1000U}};
std::cout << "u128 in [0, 1000]: " << u128_dist(rng) << std::endl;
return 0;
}
Output:
u32 in [1, 100]: 76 i32 in [-50, 50]: 14 u64 full range: 13874630024467741450 u16 in [0, 10]: 1 u128 in [0, 1000]: 904