<charconv> Support

Description

The library provides character conversion functions for safe integer types using Boost.Charconv. These functions convert between safe integer types and their string representations.

#include <boost/safe_numbers/charconv.hpp>

namespace boost::safe_numbers {

// Convert safe integer to character string
template <unsigned_integral BasisType>
constexpr auto to_chars(char* first, char* last,
                        unsigned_integer_basis<BasisType> value,
                        int base = 10) -> charconv::to_chars_result;

// Convert character string to safe integer
template <unsigned_integral BasisType>
constexpr auto from_chars(const char* first, const char* last,
                          unsigned_integer_basis<BasisType>& value,
                          int base = 10) -> charconv::from_chars_result;

} // namespace boost::safe_numbers

to_chars_result

namespace boost::charconv {

struct to_chars_result
{
    char* ptr;
    std::errc ec;

    friend constexpr bool operator==(const to_chars_result& lhs,
                                     const to_chars_result& rhs) noexcept = default;
    constexpr explicit operator bool() const noexcept { return ec == std::errc{}; }
};

} // namespace boost::charconv
Member Description

ptr

Pointer to one past the last character written on success, or last on failure

ec

Error code: std::errc{} on success, std::errc::value_too_large if buffer is too small

from_chars_result

namespace boost::charconv {

struct from_chars_result
{
    const char* ptr;
    std::errc ec;

    friend constexpr bool operator==(const from_chars_result& lhs,
                                     const from_chars_result& rhs) noexcept = default;
    constexpr explicit operator bool() const noexcept { return ec == std::errc{}; }
};

} // namespace boost::charconv
Member Description

ptr

Pointer to the first character not matching the pattern, or last if all matched

ec

Error code: std::errc{} on success, std::errc::invalid_argument if no valid conversion, std::errc::result_out_of_range if value overflows

to_chars

template <unsigned_integral BasisType>
constexpr auto to_chars(char* first, char* last,
                        unsigned_integer_basis<BasisType> value,
                        int base = 10) -> charconv::to_chars_result;

Converts a safe integer value into a character buffer specified by [first, last).

Parameters

Parameter Description

first, last

Character buffer to write to

value

The safe integer value to convert

base

Integer base (default: 10), must be between 2 and 36

Return Value

Returns boost::charconv::to_chars_result with:

  • ptr pointing to one past the last character written on success

  • ec set to std::errc{} on success, or std::errc::value_too_large if the buffer is too small

from_chars

template <unsigned_integral BasisType>
constexpr auto from_chars(const char* first, const char* last,
                          unsigned_integer_basis<BasisType>& value,
                          int base = 10) -> charconv::from_chars_result;

Parses a string from [first, last) and converts it into a safe integer value.

Parameters

Parameter Description

first, last

Character range to parse

value

Reference to safe integer to store the result

base

Integer base (default: 10), must be between 2 and 36

Return Value

Returns boost::charconv::from_chars_result with:

  • ptr pointing to the first character not matching the pattern

  • ec set to std::errc{} on success, std::errc::invalid_argument if no valid conversion, or std::errc::result_out_of_range if the value overflows

Examples

Example 1. This example demonstrates how to use to_chars and from_chars with safe integer types.
// 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/unsigned_integers.hpp>
#include <boost/safe_numbers/charconv.hpp>
#include <iostream>
#include <cstring>

int main()
{
    using namespace boost::safe_numbers;

    // to_chars: Convert safe integer to string
    u32 value {12345};
    char buffer[32];

    auto result = to_chars(buffer, buffer + sizeof(buffer), value);
    if (result)
    {
        *result.ptr = '\0';  // Null-terminate
        std::cout << "to_chars (base 10): " << buffer << '\n';
    }

    // to_chars with different bases
    result = to_chars(buffer, buffer + sizeof(buffer), value, 16);
    if (result)
    {
        *result.ptr = '\0';
        std::cout << "to_chars (base 16): " << buffer << '\n';
    }

    result = to_chars(buffer, buffer + sizeof(buffer), value, 2);
    if (result)
    {
        *result.ptr = '\0';
        std::cout << "to_chars (base 2):  " << buffer << '\n';
    }

    std::cout << '\n';

    // from_chars: Convert string to safe integer
    const char* str = "98765";
    u32 parsed_value {};

    auto parse_result = from_chars(str, str + std::strlen(str), parsed_value);
    if (parse_result)
    {
        std::cout << "from_chars (base 10): " << static_cast<std::uint32_t>(parsed_value) << '\n';
    }

    // from_chars with hexadecimal
    const char* hex_str = "1a2b";
    u32 hex_value {};

    parse_result = from_chars(hex_str, hex_str + std::strlen(hex_str), hex_value, 16);
    if (parse_result)
    {
        std::cout << "from_chars (base 16): " << static_cast<std::uint32_t>(hex_value) << '\n';
    }

    // from_chars with binary
    const char* bin_str = "11010";
    u8 bin_value {};

    parse_result = from_chars(bin_str, bin_str + std::strlen(bin_str), bin_value, 2);
    if (parse_result)
    {
        std::cout << "from_chars (base 2):  " << static_cast<unsigned>(bin_value) << '\n';
    }

    return 0;
}

Output:

to_chars (base 10): 12345
to_chars (base 16): 3039
to_chars (base 2):  11000000111001

from_chars (base 10): 98765
from_chars (base 16): 6699
from_chars (base 2):  26