Skip to content

"{}" vs "{:}" gives different constexpr behavior #3526

Description

@SamBove

When implementing a formatter specialization for a user-defined type, I was surprised to see some exceptions thrown at runtime instead of at compile time. It seems that when a replacement field has an empty format specification (i.e. "{}"), then formatter<...>::parse() gets called at runtime, whereas if there is any format specification, even if it's empty (i.e. "{:}") then parse() gets called at compile time. It would certainly be preferable for parse() to be called at compile time in the empty format specification case. Here's an example:

#include <fmt/format.h>

struct WrappedInt { int val; };

// The formatter for WrappedInt unconditionally rejects its format specifications on purpose
// to make it clear when format strings are checked at compile time vs runtime
template <>
struct fmt::formatter<WrappedInt>
{
  template <typename ParseContext>
  constexpr auto parse(ParseContext& ctx)
  {
    throw fmt::format_error("Never happy");
    return ctx.begin();
  }

  auto format(const WrappedInt& wrappedInt, format_context& ctx) const
  {
    return fmt::format_to(ctx.out(), "{}", wrappedInt.val);
  }
};

int main()
{
  // fmt::print("{:}", WrappedInt(1)); // When uncommented, this line gives a compiler error, which is ideal
  fmt::print("{}", WrappedInt(1)); // This line however, leads to an exception being thrown at runtime
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions