A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/fmtlib/fmt/issues/1467 below:

flexible std::complex formatter · Issue #1467 · fmtlib/fmt · GitHub

So... c++20 will have a formatter for std::complex (https://www.zverovich.net/2019/07/23/std-format-cpp20.html, https://wg21.link/p1636r0). In the N years between now and when that's widely available, is there something that will vaguely approximate what the standard will be? is there a proposed implementation yet? google doesn't find me anything, so...

I've come up with this, is it ok? Any ideas on how to improve it? It doesnt handle width and align properly yet. Wanted to share it at least, because I couldn't find anything like it, and hopefully someone can improve it....

If this is totally uninteresting feel free to close the issue, at least the next person searching for a std::complex formatter will be able to find a starting place :)

/// This formats a
/// complex number (a+bi) as (a+bi), offering the same formatting
/// options as the underlying type - with the addition of three
/// optional format options, only one of which may appear directly
/// after the ':' in the format spec (before any fill or align): '$'
/// (the default if no flag is specified), '*', and ',".  The '*' flag
/// adds a * before the 'i', producing (a+b*i), where a and b are the
/// formatted value_type values.  The ',' flag simply prints the real
/// and complex parts separated by a comma (same as iostreams' format).
/// As a concrete exmple, this formatter can produce either (3+5.4i)
/// or (3+5.4*i) or (3,5.4) for a complex<double> using the specs {:g}
/// | {:$g}, {:*g}, or {:,g}, respectively.  (this implementation is a
/// bit hacky - glad for cleanups).
///
template <typename T, typename Char>
struct fmt::formatter<std::complex<T>,Char> : public fmt::formatter<T,Char>
{
  typedef fmt::formatter<T,Char> base;
  enum style { expr, star, pair } style_ = expr;
  internal::dynamic_format_specs<Char> specs_;
  constexpr auto parse(format_parse_context & ctx) -> decltype(ctx.begin()) {
    using handler_type = internal::dynamic_specs_handler<format_parse_context>;
    auto type = internal::type_constant<T, Char>::value;
    internal::specs_checker<handler_type> handler(handler_type(specs_, ctx), type);
    auto it = ctx.begin();
    switch (*it) {
    case '$': style_ = style::expr; ctx.advance_to(++it); break;
    case '*': style_ = style::star; ctx.advance_to(++it); break;
    case ',': style_ = style::pair; ctx.advance_to(++it); break;
    default: break;
    }
    if (style_ != style::pair)
      parse_format_specs(ctx.begin(), ctx.end(), handler);
    //todo: fixup alignment
    return base::parse(ctx);
  }
  template <typename FormatCtx>
  auto format(const std::complex<T> & x, FormatCtx & ctx) -> decltype(ctx.out()) {
    format_to(ctx.out(), "(");
    if (x.real() || !x.imag())
      base::format(x.real(), ctx);
    if (x.imag()) {
      if (style_ == style::pair)
        format_to(ctx.out(), ",");
      else
        if (x.real() && x.imag() >= 0 && specs_.sign != sign::plus)
          format_to(ctx.out(), "+");
      base::format(x.imag(), ctx);
      if (style_ != style::pair) {
        if (style_ == style::star)
          format_to(ctx.out(), "*i");
        else
          format_to(ctx.out(), "i");
        if (std::is_same<typename std::decay<T>::type,float>::value)       format_to(ctx.out(), "f");
        if (std::is_same<typename std::decay<T>::type,long double>::value) format_to(ctx.out(), "l");
      }
    }
    return format_to(ctx.out(), ")");
  }
};

vitaut, sehe, plevold and IRainman


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4