Skip to content

<format>: Underlying formatters of pair-or-tuple formatter cannot access format args #4651

@JMazurkiewicz

Description

@JMazurkiewicz

Underlying formatters of pair-or-tuple formatter should be able to call format_ctx.arg(I) and get correct format arg.

Example:

#include <print>
#include <thread>

template <size_t I> struct substitute_arg {};

template <size_t I> struct std::formatter<substitute_arg<I>> {
  template <class ParseContext> constexpr auto parse(ParseContext &ctx) {
    auto it = ctx.begin();
    if (it != ctx.end() && *it != '}') {
      throw format_error{"Expected empty spec"};
    }

    ctx.check_arg_id(I);
    return it;
  }

  template <class FormatContext>
  auto format(substitute_arg<I>, FormatContext &ctx) const {
    auto visitor = [&]<class T>(T val) -> FormatContext::iterator {
      if constexpr (same_as<T, monostate>) {
        return ranges::copy("monostate"sv, ctx.out()).out;
      } else if constexpr (same_as<T, typename basic_format_arg<
                                          FormatContext>::handle>) {
        format_parse_context parse_ctx{""};
        val.format(parse_ctx, ctx);
        return ctx.out();
      } else {
        return format_to(ctx.out(), "{}", val);
      }
    };

    return visit_format_arg(visitor, ctx.arg(I));
  }
};

int main() {
  std::println("{0:}", std::tuple{substitute_arg<1>{}, substitute_arg<2>{}},
               "thread::id", std::thread::id{});
}

Expected output (libc++: https://godbolt.org/z/1c4fdhzTb):

(thread::id, 0)

We've got:

(monostate, monostate)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingfixedSomething works now, yay!formatC++20/23 format

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions