c++ format unordered map with fmt::join

Viewed 600

I'm trying to create a libfmt formatter for a std::unordered_map<std::string, Foo> using fmt::join but I can't seem to get it to work:

#include <fmt/core.h>
#include <fmt/format.h>
#include <unordered_map>

struct Foo{
  int a;
};

using FooPair = std::pair<std::string, Foo>;
using FooMap = std::unordered_map<std::string, Foo>;


namespace fmt{

template <>
struct formatter<Foo> {
  template <typename ParseContext>
  constexpr auto parse(ParseContext& ctx) {
    return ctx.begin();
  }

  template <typename FormatContext>
  auto format(const Foo& f, FormatContext& ctx) {
    return format_to(ctx.out(), "\n    {}", f.a);
  }
};

template <>
struct formatter<FooPair> {
  template <typename ParseContext>
  constexpr auto parse(ParseContext& ctx) {
    return ctx.begin();
  }

  template <typename FormatContext>
  auto format(const FooPair& fp, FormatContext& ctx) {
    return format_to(ctx.out(), "\n  {}{}", fp.first, fp.second);
  }
};


template <>
struct formatter<FooMap> {
  template <typename ParseContext>
  constexpr auto parse(ParseContext& ctx) {
    return ctx.begin();
  }

  template <typename FormatContext>
  auto format(const FooMap& fm, FormatContext& ctx) {
    return format_to(ctx.out(), "{}", fmt::join(fm.begin(), fm.end(), ""));
  }
};


}




int main(){


FooMap foomap;

fmt::print("Foo Map: {}", foomap);

}

It looks like I'm missing a formatter for an iterator, but I tried defining that as well as one for a const_iterator to no avail. Minimum example here: https://godbolt.org/z/q4615csG6

I'm sure I'm just leaving something stupid out, I just can't see it at the moment.

1 Answers

Here is fixed version:
https://godbolt.org/z/r6dGfzesz

using FooMap = std::unordered_map<std::string, Foo>;
using FooPair = FooMap::value_type;

Problem is this: using FooPair = std::pair<std::string, Foo>;. Note documentation of unordered_map:
std::unordered_map - cppreference.com

value_type std::pair<const Key, T>

So problems is not matching types: one pair contains const for key (first) other is not.

So other way to fix it:

using FooPair = std::pair<const std::string, Foo>;

https://godbolt.org/z/9KT9j6h1b

Related