toml11
toml11 copied to clipboard
How to print `toml::value` returned from `toml::parse()` with `fmt::print()` properly?
Problem Description
It is related to the issue: https://github.com/fmtlib/fmt/issues/2894
According to vitaut's comment:
{fmt} doesn't provide formatters for toml11 types. You should check which formatter is being used and address your question to its author.
What should I do?
First of all, since I'm not an author of {fmt}, I don't know much about the implementation detail of the library. But I took a glance at the code and found that the example code shown in your link seems to use fallback_formatter
that internally calls operator<<(ostream&, T)
. If I'm not mistaken, it does not set std::setw
. Since operator<<(ostream&, toml::value)
reads width setting in ostream
, if width
is not set, it does nothing.
There are several options:
- implementing {fmt} formatter that parses width specifier and pass it to
setw
ortoml::format
. I think this is the most appropriate (but could be painful) way. - wrapping a
toml::value
by astruct
that haswidth
and defineoperator<<
to usewidth
internally. This is easy but makes code messy.
{fmt} documentation explains how to write a formatter: https://fmt.dev/latest/api.html#format-api.
The second option will look like:
#define FMT_DEPRECATED_OSTREAM
#include <fmt/format.h>
#include <fmt/ostream.h>
#include <toml.hpp>
#include <iostream>
struct width_setter
{
width_setter(std::size_t w, const toml::value& v): width_(w), data_(v) {}
std::size_t width_;
toml::value const& data_;
};
template <typename charT, typename traits>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const width_setter& w)
{
os << std::setw(w.width_) << w.data_;
return os;
}
int main(int argc, char **argv)
{
if(argc != 2)
{
fmt::print("usage: ./toml11fmt example.toml\n");
return 1;
}
const auto data = toml::parse(std::string(argv[1]));
std::cout << std::setw(80) << data << std::endl;
fmt::print(std::cout, "{}", width_setter(80, data));
return 0;
}