P3953R3
Rename std::runtime_format

Published Proposal,

Author:
Audience:
LEWG
Project:
ISO/IEC 14882 Programming Languages — C++, ISO/IEC JTC1/SC22/WG21

There are only two hard things in Computer Science: cache invalidation and naming things.
— Phil Karlton

1. Abstract

[P2918] introduced std::runtime_format to allow opting out of compile-time format string checks in std::format. Subsequently, [P3391] made std::format usable in constant evaluation. As a result, std::runtime_format can now be evaluated at compile time, making its name misleading. This paper proposes renaming std::runtime_format to std::dynamic_format to better reflect its semantics and avoid confusion in constexpr contexts.

2. Changes since R2

3. Changes since R1

4. Changes since R0

5. Motivation

The name std::runtime_format was accurate when introduced in [P2918], as format strings were not usable in constant evaluation. However, with the adoption of constexpr std::format, the term runtime no longer reliably describes the behavior of std::runtime_format.

Consider the following code:

constexpr auto f(std::string_view fmt, int value) {
  return std::format(std::runtime_format(fmt), value);
}

Despite its name, std::runtime_format can be evaluated at compile time. This creates a semantic mismatch:

The real distinction is not when formatting occurs, but how the format string is provided and validated. The term runtime conflates it with evaluation time.

6. Proposed Naming: std::dynamic_format

The proposed name std::dynamic_format reflects the actual semantics:

This aligns with existing terminology std::format such as dynamic format specifiers (check_dynamic_spec).

Example with proposed name:

constexpr auto f(std::string_view fmt, int value) {
  return std::format(std::dynamic_format(fmt), value);
}

This reads naturally and avoids semantic contradiction.

7. Impact on existing code

If this is adopted for C++26 there will be no impact on existing code since std::runtime_format is a C++26 feature.

8. Wording

Update the value of the feature-testing macro __cpp_lib_format to the date of adoption in [version.syn].

Modify "Header <format> synopsis" [format.syn]:

template<class charT> struct runtimedynamic-format-string {    // exposition only
private:
  basic_string_view<charT> str;    // exposition only
public:
  constexpr runtimedynamic-format-string(basic_string_view<charT> s) noexcept : str(s) {}
  runtimedynamic-format-string(const runtimedynamic-format-string&) = delete;
  runtimedynamic-format-string& operator=(const runtimedynamic-format-string&) = delete;
};
constexpr runtimedynamic-format-string<char>
  runtimedynamic_format(string_view fmt) noexcept { return fmt; }
constexpr runtimedynamic-format-string<wchar_t>
  runtimedynamic_format(wstring_view fmt) noexcept { return fmt; }

Modify "Class template basic_format_string" [format.fmt.string]:

namespace std {
  template<class charT, class... Args>
  struct basic_format_string {
  private:
    basic_string_view<charT> str;    // exposition only

  public:
    template<class T> consteval basic_format_string(const T& s);
    constexpr basic_format_string(runtimedynamic-format-string<charT> s) noexcept : str(s.str) {}

    constexpr basic_string_view<charT> get() const noexcept { return str; }
  };
}

References

Informative References

[P2918]
Victor Zverovich. Runtime format strings II. URL: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2918r2.html
[P3391]
Barry Revzin. `constexpr std::format`. URL: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3391r2.html