Skip to content

Make std::formatter usable with exceptions disabled - #3

Merged
cleishm merged 2 commits into
mainfrom
fix/no-exceptions-format
Aug 7, 2026
Merged

Make std::formatter usable with exceptions disabled#3
cleishm merged 2 commits into
mainfrom
fix/no-exceptions-format

Conversation

@cleishm

@cleishm cleishm commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Problem

The std::formatter specialization's parse() reported an unusable format spec (a precision with no SI prefix, formatted with an empty spec) with a bare throw format_error(...). Under -fno-exceptions — the default on embedded targets such as ESP-IDF with CONFIG_COMPILER_CXX_EXCEPTIONS unset — a throw in any instantiated function is a hard compile error, so even a perfectly valid std::format("{}", kilohertz(433)) failed to compile.

Same bug and fix as cleishm/thermo-cpp#7.

Fix

  • The error branch is discarded via if constexpr when the precision has an SI prefix, so it is never instantiated for formatters that cannot need it.
  • When it is needed, the error is reported through a new _format_error() helper: it throws std::format_error when exceptions are available, and calls std::abort() when they are not. Because the helper is not constexpr, consteval format-string checking still rejects a bad spec at compile time in both modes; the abort is only reachable through a runtime format string (std::vformat) with exceptions disabled, where there is no way to report the error.

Tests

  • New tests/no_exceptions_test.cpp: a framework-free target compiled with -fno-exceptions exercising the formatter with empty and explicit specs (Catch2 requires exceptions, so it cannot live in frequency_tests). Skipped on MSVC, which spells the option differently and declares __cpp_exceptions regardless.
  • Verified the prefix-less empty-spec case (e.g. std::deci) still fails to compile with and without exceptions.
  • Full suite passes: 44/44.

Bumps version to 1.2.1 (CMakeLists, idf_component.yml, docs/Doxyfile, vcpkg-port/vcpkg.json).

cleishm added 2 commits August 7, 2026 14:15
The formatter specialization's parse() reported an unusable format spec
(a precision with no SI prefix and an empty spec) with a bare throw,
which is a hard compile error under -fno-exceptions for any use of the
formatter — even valid ones — making it unusable on embedded targets
such as ESP-IDF with CONFIG_COMPILER_CXX_EXCEPTIONS unset.

The error branch is now discarded via `if constexpr` when the precision
has an SI prefix, and otherwise reports through a _format_error() helper
that throws std::format_error when exceptions are available and calls
std::abort() when they are not. Because the helper is not constexpr,
constant evaluation of the format string still rejects a bad spec at
compile time in both modes.

Adds a framework-free test target built with -fno-exceptions (Catch2
requires exceptions, so it cannot live in frequency_tests).

Same fix as thermo-cpp#7.
@cleishm
cleishm merged commit 885b6b6 into main Aug 7, 2026
6 checks passed
@cleishm
cleishm deleted the fix/no-exceptions-format branch August 7, 2026 21:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant