+FMT_BEGIN_DETAIL_NAMESPACE
+// A parse context with extra data used only in compile-time checks.
+template <typename Char, typename ErrorHandler = detail::error_handler>
+class compile_parse_context
+ : public basic_format_parse_context<Char, ErrorHandler> {
+ private:
+ int num_args_;
+ const type* types_;
+ using base = basic_format_parse_context<Char, ErrorHandler>;
+
+ public:
+ explicit FMT_CONSTEXPR compile_parse_context(
+ basic_string_view<Char> format_str, int num_args, const type* types,
+ ErrorHandler eh = {}, int next_arg_id = 0)
+ : base(format_str, eh, next_arg_id), num_args_(num_args), types_(types) {}
+
+ constexpr auto num_args() const -> int { return num_args_; }
+ constexpr auto arg_type(int id) const -> type { return types_[id]; }
+
+ FMT_CONSTEXPR auto next_arg_id() -> int {
+ int id = base::next_arg_id();
+ if (id >= num_args_) this->on_error("argument not found");
+ return id;
+ }
+
+ FMT_CONSTEXPR void check_arg_id(int id) {
+ base::check_arg_id(id);
+ if (id >= num_args_) this->on_error("argument not found");
+ }
+ using base::check_arg_id;
+
+ FMT_CONSTEXPR void check_dynamic_spec(int arg_id) {
+ if (arg_id < num_args_ && types_ && !is_integral_type(types_[arg_id]))
+ this->on_error("width/precision is not integer");
+ }
+};
+FMT_END_DETAIL_NAMESPACE
+
+template <typename Char, typename ErrorHandler>
+FMT_CONSTEXPR void
+basic_format_parse_context<Char, ErrorHandler>::do_check_arg_id(int id) {
+ // Argument id is only checked at compile-time during parsing because
+ // formatting has its own validation.
+ if (detail::is_constant_evaluated() && FMT_GCC_VERSION >= 1200) {
+ using context = detail::compile_parse_context<Char, ErrorHandler>;
+ if (id >= static_cast<context*>(this)->num_args())
+ on_error("argument not found");
+ }
+}
+
+template <typename Char, typename ErrorHandler>
+FMT_CONSTEXPR void
+basic_format_parse_context<Char, ErrorHandler>::check_dynamic_spec(int arg_id) {
+ if (detail::is_constant_evaluated()) {
+ using context = detail::compile_parse_context<Char, ErrorHandler>;
+ static_cast<context*>(this)->check_dynamic_spec(arg_id);
+ }
+}
+